mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-02-02 12:19:18 +00:00
drawing tool
This commit is contained in:
parent
5c98118da3
commit
ad233a1e19
@ -4630,6 +4630,8 @@ EX void drawthemap() {
|
|||||||
profile_stop(4);
|
profile_stop(4);
|
||||||
drawFlashes();
|
drawFlashes();
|
||||||
|
|
||||||
|
mapeditor::draw_dtshapes();
|
||||||
|
|
||||||
if(multi::players > 1 && !shmup::on) {
|
if(multi::players > 1 && !shmup::on) {
|
||||||
if(multi::centerplayer != -1)
|
if(multi::centerplayer != -1)
|
||||||
cwtV = multi::whereis[multi::centerplayer];
|
cwtV = multi::whereis[multi::centerplayer];
|
||||||
|
4
hyper.h
4
hyper.h
@ -13,8 +13,8 @@
|
|||||||
#define _HYPER_H_
|
#define _HYPER_H_
|
||||||
|
|
||||||
// version numbers
|
// version numbers
|
||||||
#define VER "11.3i"
|
#define VER "11.3j"
|
||||||
#define VERNUM_HEX 0xA829
|
#define VERNUM_HEX 0xA82A
|
||||||
|
|
||||||
#include "sysconfig.h"
|
#include "sysconfig.h"
|
||||||
|
|
||||||
|
404
mapeditor.cpp
404
mapeditor.cpp
@ -10,11 +10,224 @@ namespace hr {
|
|||||||
|
|
||||||
EX namespace mapeditor {
|
EX namespace mapeditor {
|
||||||
|
|
||||||
|
EX bool drawing_tool;
|
||||||
|
|
||||||
#if HDR
|
#if HDR
|
||||||
enum eShapegroup { sgPlayer, sgMonster, sgItem, sgFloor, sgWall };
|
enum eShapegroup { sgPlayer, sgMonster, sgItem, sgFloor, sgWall };
|
||||||
static const int USERSHAPEGROUPS = 5;
|
static const int USERSHAPEGROUPS = 5;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
color_t dtfill;
|
||||||
|
|
||||||
|
/* drawing_tool shapes */
|
||||||
|
struct dtshape {
|
||||||
|
cell *where;
|
||||||
|
color_t col, fill;
|
||||||
|
ld lw;
|
||||||
|
|
||||||
|
virtual void rotate(const transmatrix& T) = 0;
|
||||||
|
virtual void save(hstream& hs) = 0;
|
||||||
|
virtual dtshape* load(hstream& hs) = 0;
|
||||||
|
virtual void draw(const transmatrix& V) = 0;
|
||||||
|
virtual ld distance(hyperpoint h) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dtline : dtshape {
|
||||||
|
|
||||||
|
hyperpoint s, e;
|
||||||
|
|
||||||
|
void rotate(const transmatrix& T) override {
|
||||||
|
s = T * s;
|
||||||
|
e = T * e;
|
||||||
|
}
|
||||||
|
void save(hstream& hs) override {
|
||||||
|
hs.write<char>(1);
|
||||||
|
hs.write(s);
|
||||||
|
hs.write(e);
|
||||||
|
}
|
||||||
|
dtshape *load(hstream& hs) override {
|
||||||
|
hs.read(s);
|
||||||
|
hs.read(e);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
void draw(const transmatrix& V) override {
|
||||||
|
queueline(V*s, V*e, col, 2 + vid.linequality);
|
||||||
|
}
|
||||||
|
ld distance(hyperpoint h) override {
|
||||||
|
return hdist(s, h) + hdist(e, h) - hdist(s, e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dtcircle : dtshape {
|
||||||
|
|
||||||
|
hyperpoint s; ld radius;
|
||||||
|
|
||||||
|
void rotate(const transmatrix& T) override {
|
||||||
|
s = T * s;
|
||||||
|
}
|
||||||
|
void save(hstream& hs) override {
|
||||||
|
hs.write<char>(2);
|
||||||
|
hs.write(s);
|
||||||
|
hs.write(radius);
|
||||||
|
}
|
||||||
|
dtshape *load(hstream& hs) override {
|
||||||
|
hs.read(s);
|
||||||
|
hs.read(radius);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
void draw(const transmatrix& V) override {
|
||||||
|
ld len = sin_auto(radius);
|
||||||
|
int ll = ceil(360 * len);
|
||||||
|
transmatrix W = V * rgpushxto0(s);
|
||||||
|
for(int i=0; i<=ll; i++)
|
||||||
|
curvepoint(W * xspinpush0(360*degree*i/ll, radius));
|
||||||
|
queuecurve(col, fill, PPR::LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ld distance(hyperpoint h) override {
|
||||||
|
return abs(hdist(s, h) - radius);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dtfree : dtshape {
|
||||||
|
|
||||||
|
vector<hyperpoint> lh;
|
||||||
|
|
||||||
|
void rotate(const transmatrix& T) override {
|
||||||
|
for(auto& h: lh) h = T * h;
|
||||||
|
}
|
||||||
|
void save(hstream& hs) override {
|
||||||
|
hs.write<char>(3);
|
||||||
|
hs.write(lh);
|
||||||
|
}
|
||||||
|
dtshape *load(hstream& hs) override {
|
||||||
|
hs.read(lh);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
void draw(const transmatrix& V) override {
|
||||||
|
for(auto& p: lh) curvepoint(V*p);
|
||||||
|
queuecurve(col, fill, PPR::LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ld distance(hyperpoint h) override {
|
||||||
|
ld mind = 99;
|
||||||
|
for(auto h1: lh) mind = min(mind, hdist(h, h1));
|
||||||
|
return mind;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vector<unique_ptr<dtshape>> dtshapes;
|
||||||
|
|
||||||
|
EX void draw_dtshapes() {
|
||||||
|
for(auto& shp: dtshapes) {
|
||||||
|
if(shp == nullptr) continue;
|
||||||
|
auto& sh = *shp;
|
||||||
|
cell*& c = sh.where;
|
||||||
|
for(const transmatrix& V: current_display->all_drawn_copies[c]) {
|
||||||
|
dynamicval<ld> lw(vid.linewidth, vid.linewidth * sh.lw);
|
||||||
|
sh.draw(V);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** dtshapes takes ownership of sh */
|
||||||
|
void dt_add(cell *where, dtshape *sh) {
|
||||||
|
sh->where = where;
|
||||||
|
sh->col = texture::config.paint_color;
|
||||||
|
sh->fill = dtfill;
|
||||||
|
sh->lw = texture::penwidth * 100;
|
||||||
|
|
||||||
|
dtshapes.push_back(unique_ptr<dtshape>(sh));
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void dt_add_line(hyperpoint h1, hyperpoint h2, int maxl) {
|
||||||
|
if(hdist(h1, h2) > 1 && maxl > 0) {
|
||||||
|
hyperpoint h3 = mid(h1, h2);
|
||||||
|
dt_add_line(h1, h3, maxl-1);
|
||||||
|
dt_add_line(h3, h2, maxl-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cell *b = centerover;
|
||||||
|
transmatrix T = rgpushxto0(h1);
|
||||||
|
|
||||||
|
auto T1 = inverse(ggmatrix(b)) * T;
|
||||||
|
virtualRebase(b, T1);
|
||||||
|
|
||||||
|
auto l = new dtline;
|
||||||
|
l->s = tC0(T1);
|
||||||
|
l->e = T1 * gpushxto0(h1) * h2;
|
||||||
|
dt_add(b, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void dt_add_circle(hyperpoint h1, hyperpoint h2) {
|
||||||
|
cell *b = centerover;
|
||||||
|
|
||||||
|
auto d = hdist(h1, h2);
|
||||||
|
|
||||||
|
h1 = inverse(ggmatrix(b)) * h1;
|
||||||
|
virtualRebase(b, h1);
|
||||||
|
|
||||||
|
auto l = new dtcircle;
|
||||||
|
l->s = h1;
|
||||||
|
l->radius = d;
|
||||||
|
dt_add(b, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
dtshape *load_shape(hstream& hs) {
|
||||||
|
char type = hs.get<char>();
|
||||||
|
switch(type) {
|
||||||
|
case 1:
|
||||||
|
return (new dtline)->load(hs);
|
||||||
|
case 2:
|
||||||
|
return (new dtcircle)->load(hs);
|
||||||
|
case 3:
|
||||||
|
return (new dtfree)->load(hs);
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dtfree *cfree;
|
||||||
|
cell *cfree_at;
|
||||||
|
transmatrix cfree_T;
|
||||||
|
|
||||||
|
EX void dt_add_free(hyperpoint h) {
|
||||||
|
|
||||||
|
cell *b = centerover;
|
||||||
|
transmatrix T = rgpushxto0(h);
|
||||||
|
auto T1 = inverse(ggmatrix(b)) * T;
|
||||||
|
virtualRebase(b, T1);
|
||||||
|
|
||||||
|
if(cfree)
|
||||||
|
cfree->lh.push_back(cfree_T * h);
|
||||||
|
|
||||||
|
if(b != cfree_at && !(dtfill && cfree_at)) {
|
||||||
|
cfree = new dtfree;
|
||||||
|
dt_add(b, cfree);
|
||||||
|
cfree_T = T1 * gpushxto0(h);
|
||||||
|
cfree->lh.push_back(cfree_T * h);
|
||||||
|
cfree_at = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void dt_erase(hyperpoint h) {
|
||||||
|
ld nearest = 1;
|
||||||
|
int nearest_id = -1;
|
||||||
|
int id = -1;
|
||||||
|
for(auto& shp: dtshapes) {
|
||||||
|
id++;
|
||||||
|
if(shp == nullptr) continue;
|
||||||
|
auto& sh = *shp;
|
||||||
|
cell*& c = sh.where;
|
||||||
|
for(const transmatrix& V: current_display->all_drawn_copies[c]) {
|
||||||
|
ld dist = sh.distance(inverse(V) * h);
|
||||||
|
if(dist < nearest) nearest = dist, nearest_id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(nearest_id >= 0)
|
||||||
|
dtshapes.erase(dtshapes.begin() + nearest_id);
|
||||||
|
}
|
||||||
|
|
||||||
hyperpoint lstart;
|
hyperpoint lstart;
|
||||||
cell *lstartcell;
|
cell *lstartcell;
|
||||||
ld front_edit = 0.5;
|
ld front_edit = 0.5;
|
||||||
@ -101,6 +314,39 @@ namespace mapstream {
|
|||||||
vector<cell*> cellbyid;
|
vector<cell*> cellbyid;
|
||||||
vector<char> relspin;
|
vector<char> relspin;
|
||||||
|
|
||||||
|
void load_drawing_tool(fhstream& hs) {
|
||||||
|
using namespace mapeditor;
|
||||||
|
if(hs.vernum < 0xA82A) return;
|
||||||
|
int i = hs.get<int>();
|
||||||
|
while(i--) {
|
||||||
|
auto sh = load_shape(hs);
|
||||||
|
if(!sh) continue;
|
||||||
|
hs.read(sh->col);
|
||||||
|
hs.read(sh->fill);
|
||||||
|
hs.read(sh->lw);
|
||||||
|
int id = hs.get<int>();
|
||||||
|
sh->where = cellbyid[id];
|
||||||
|
sh->rotate(spin(currentmap->spin_angle(sh->where, relspin[id]) - currentmap->spin_angle(sh->where, 0)));
|
||||||
|
dtshapes.push_back(unique_ptr<dtshape>(sh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_drawing_tool(hstream& hs) {
|
||||||
|
using namespace mapeditor;
|
||||||
|
hs.write<int>(isize(dtshapes));
|
||||||
|
for(auto& shp: dtshapes) {
|
||||||
|
if(shp == nullptr) { hs.write<char>(0); }
|
||||||
|
else {
|
||||||
|
auto& sh = *shp;
|
||||||
|
sh.save(hs);
|
||||||
|
hs.write(sh.col);
|
||||||
|
hs.write(sh.fill);
|
||||||
|
hs.write(sh.lw);
|
||||||
|
hs.write(cellids[sh.where]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void addToQueue(cell* c) {
|
void addToQueue(cell* c) {
|
||||||
if(cellids.count(c)) return;
|
if(cellids.count(c)) return;
|
||||||
@ -326,6 +572,8 @@ namespace mapstream {
|
|||||||
int32_t id = cellids.count(cwt.at) ? cellids[cwt.at] : -1;
|
int32_t id = cellids.count(cwt.at) ? cellids[cwt.at] : -1;
|
||||||
f.write(id);
|
f.write(id);
|
||||||
|
|
||||||
|
save_drawing_tool(f);
|
||||||
|
|
||||||
f.write(vid.always3);
|
f.write(vid.always3);
|
||||||
f.write(mutantphase);
|
f.write(mutantphase);
|
||||||
f.write(rosewave);
|
f.write(rosewave);
|
||||||
@ -507,6 +755,8 @@ namespace mapstream {
|
|||||||
savecount = 0; savetime = 0;
|
savecount = 0; savetime = 0;
|
||||||
cheater = 1;
|
cheater = 1;
|
||||||
|
|
||||||
|
load_drawing_tool(f);
|
||||||
|
|
||||||
dynamicval<bool> a3(vid.always3, vid.always3);
|
dynamicval<bool> a3(vid.always3, vid.always3);
|
||||||
if(f.vernum >= 0xA616) { f.read(vid.always3); geom3::apply_always3(); }
|
if(f.vernum >= 0xA616) { f.read(vid.always3); geom3::apply_always3(); }
|
||||||
|
|
||||||
@ -984,6 +1234,32 @@ namespace mapeditor {
|
|||||||
return cellwalker(mouseover, d);
|
return cellwalker(mouseover, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void save_level() {
|
||||||
|
dialog::openFileDialog(levelfile, XLAT("level to save:"), ".lev", [] () {
|
||||||
|
if(mapstream::saveMap(levelfile.c_str())) {
|
||||||
|
addMessage(XLAT("Map saved to %1", levelfile));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addMessage(XLAT("Failed to save map to %1", levelfile));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_level() {
|
||||||
|
dialog::openFileDialog(levelfile, XLAT("level to load:"), ".lev", [] () {
|
||||||
|
if(mapstream::loadMap(levelfile.c_str())) {
|
||||||
|
addMessage(XLAT("Map loaded from %1", levelfile));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addMessage(XLAT("Failed to load map from %1", levelfile));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void showList() {
|
void showList() {
|
||||||
dialog::v.clear();
|
dialog::v.clear();
|
||||||
if(painttype == 4) painttype = 0;
|
if(painttype == 4) painttype = 0;
|
||||||
@ -1085,29 +1361,8 @@ namespace mapeditor {
|
|||||||
else if(sym == SDLK_F5) {
|
else if(sym == SDLK_F5) {
|
||||||
restart_game();
|
restart_game();
|
||||||
}
|
}
|
||||||
else if(sym == SDLK_F2) {
|
else if(sym == SDLK_F2) save_level();
|
||||||
dialog::openFileDialog(levelfile, XLAT("level to save:"), ".lev", [] () {
|
else if(sym == SDLK_F3) load_level();
|
||||||
if(mapstream::saveMap(levelfile.c_str())) {
|
|
||||||
addMessage(XLAT("Map saved to %1", levelfile));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
addMessage(XLAT("Failed to save map to %1", levelfile));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if(sym == SDLK_F3)
|
|
||||||
dialog::openFileDialog(levelfile, XLAT("level to load:"), ".lev", [] () {
|
|
||||||
if(mapstream::loadMap(levelfile.c_str())) {
|
|
||||||
addMessage(XLAT("Map loaded from %1", levelfile));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
addMessage(XLAT("Failed to load map from %1", levelfile));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
#if CAP_SHOT
|
#if CAP_SHOT
|
||||||
else if(sym == SDLK_F6) {
|
else if(sym == SDLK_F6) {
|
||||||
pushScreen(shot::menu);
|
pushScreen(shot::menu);
|
||||||
@ -1363,6 +1618,9 @@ namespace mapeditor {
|
|||||||
usershape *us = NULL;
|
usershape *us = NULL;
|
||||||
|
|
||||||
bool intexture = false;
|
bool intexture = false;
|
||||||
|
(void) intexture;
|
||||||
|
|
||||||
|
bool freedraw = drawing_tool;
|
||||||
|
|
||||||
#if CAP_TEXTURE
|
#if CAP_TEXTURE
|
||||||
if(texture::config.tstate == texture::tsActive) {
|
if(texture::config.tstate == texture::tsActive) {
|
||||||
@ -1371,12 +1629,27 @@ namespace mapeditor {
|
|||||||
line2 = "";
|
line2 = "";
|
||||||
texture::config.data.update();
|
texture::config.data.update();
|
||||||
intexture = true;
|
intexture = true;
|
||||||
|
freedraw = true;
|
||||||
|
drawing_tool = false;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if(0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
else {
|
if(drawing_tool && !mouseout()) {
|
||||||
|
initquickqueue();
|
||||||
|
dynamicval<ld> lw(vid.linewidth, vid.linewidth * texture::penwidth * 100);
|
||||||
|
if(holdmouse && mousekey == 'c')
|
||||||
|
queue_hcircle(rgpushxto0(lstart), hdist(lstart, mouseh));
|
||||||
|
else if(holdmouse && mousekey == 'l')
|
||||||
|
queueline(lstart, mouseh, texture::config.paint_color, 4 + vid.linequality, PPR::LINE);
|
||||||
|
else if(!holdmouse) {
|
||||||
|
transmatrix T = rgpushxto0(mouseh);
|
||||||
|
queueline(T * xpush0(-.1), T * xpush0(.1), texture::config.paint_color);
|
||||||
|
queueline(T * ypush0(-.1), T * ypush0(.1), texture::config.paint_color);
|
||||||
|
}
|
||||||
|
quickqueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!freedraw) {
|
||||||
|
|
||||||
sg = drawcellShapeGroup();
|
sg = drawcellShapeGroup();
|
||||||
|
|
||||||
@ -1419,7 +1692,7 @@ namespace mapeditor {
|
|||||||
// displayButton(8, 8+fs*9, XLAT("l = lands"), 'l', 0);
|
// displayButton(8, 8+fs*9, XLAT("l = lands"), 'l', 0);
|
||||||
displayfr(8, 8+fs, 2, vid.fsize, line1, 0xC0C0C0, 0);
|
displayfr(8, 8+fs, 2, vid.fsize, line1, 0xC0C0C0, 0);
|
||||||
|
|
||||||
if(!intexture) {
|
if(!freedraw) {
|
||||||
if(sg == sgFloor)
|
if(sg == sgFloor)
|
||||||
displayButton(8, 8+fs*2, line2 + XLAT(" (r = complex tesselations)"), 'r', 0);
|
displayButton(8, 8+fs*2, line2 + XLAT(" (r = complex tesselations)"), 'r', 0);
|
||||||
else
|
else
|
||||||
@ -1466,17 +1739,21 @@ namespace mapeditor {
|
|||||||
|
|
||||||
}
|
}
|
||||||
#if CAP_TEXTURE
|
#if CAP_TEXTURE
|
||||||
else if(texture::config.tstate == texture::tsActive) {
|
else if(freedraw) {
|
||||||
displayButton(8, 8+fs*2, XLAT(texture::texturesym ? "0 = symmetry" : "0 = asymmetry"), '0', 0);
|
displayButton(8, 8+fs*2, XLAT(texture::texturesym ? "0 = symmetry" : "0 = asymmetry"), '0', 0);
|
||||||
if(mousekey == 'g')
|
if(mousekey == 'g')
|
||||||
displayButton(8, 8+fs*16, XLAT("p = grid color"), 'p', 0);
|
displayButton(8, 8+fs*16, XLAT("p = grid color"), 'p', 0);
|
||||||
else
|
else
|
||||||
displayButton(8, 8+fs*16, XLAT("p = color"), 'p', 0);
|
displayButton(8, 8+fs*16, XLAT("p = color"), 'p', 0);
|
||||||
|
if(drawing_tool)
|
||||||
|
displayButton(8, 8+fs*17, XLAT("f = fill") + (dtfill ? " (on)" : " (off)"), 'f', 0);
|
||||||
displayButton(8, 8+fs*4, XLAT("b = brush size: %1", fts(texture::penwidth)), 'b', 0);
|
displayButton(8, 8+fs*4, XLAT("b = brush size: %1", fts(texture::penwidth)), 'b', 0);
|
||||||
displayButton(8, 8+fs*5, XLAT("u = undo"), 'u', 0);
|
displayButton(8, 8+fs*5, XLAT("u = undo"), 'u', 0);
|
||||||
displaymm('d', 8, 8+fs*7, 2, vid.fsize, XLAT("d = draw"), 0);
|
displaymm('d', 8, 8+fs*7, 2, vid.fsize, XLAT("d = draw"), 0);
|
||||||
displaymm('l', 8, 8+fs*8, 2, vid.fsize, XLAT("l = line"), 0);
|
displaymm('l', 8, 8+fs*8, 2, vid.fsize, XLAT("l = line"), 0);
|
||||||
displaymm('c', 8, 8+fs*9, 2, vid.fsize, XLAT("c = circle"), 0);
|
displaymm('c', 8, 8+fs*9, 2, vid.fsize, XLAT("c = circle"), 0);
|
||||||
|
if(drawing_tool)
|
||||||
|
displaymm('e', 8, 8+fs*10, 2, vid.fsize, XLAT("e = erase"), 0);
|
||||||
int s = isize(texture::config.data.pixels_to_draw);
|
int s = isize(texture::config.data.pixels_to_draw);
|
||||||
if(s) displaymm(0, 8, 8+fs*11, 2, vid.fsize, its(s), 0);
|
if(s) displaymm(0, 8, 8+fs*11, 2, vid.fsize, its(s), 0);
|
||||||
}
|
}
|
||||||
@ -1498,7 +1775,7 @@ namespace mapeditor {
|
|||||||
displaymm('g', vid.xres-8, 8+fs*4, 2, vid.fsize, XLAT("g = grid"), 16);
|
displaymm('g', vid.xres-8, 8+fs*4, 2, vid.fsize, XLAT("g = grid"), 16);
|
||||||
|
|
||||||
#if CAP_TEXTURE
|
#if CAP_TEXTURE
|
||||||
if(intexture) for(int i=0; i<10; i++) {
|
if(freedraw) for(int i=0; i<10; i++) {
|
||||||
if(8 + fs * (6+i) < vid.yres - 8 - fs * 7)
|
if(8 + fs * (6+i) < vid.yres - 8 - fs * 7)
|
||||||
displayColorButton(vid.xres-8, 8+fs*(6+i), "###", 1000 + i, 16, 1, dialog::displaycolor(texture_colors[i+1]));
|
displayColorButton(vid.xres-8, 8+fs*(6+i), "###", 1000 + i, 16, 1, dialog::displaycolor(texture_colors[i+1]));
|
||||||
|
|
||||||
@ -1506,7 +1783,7 @@ namespace mapeditor {
|
|||||||
getcstat = 2000+i;
|
getcstat = 2000+i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(texture::config.tstate != texture::tsActive)
|
if(!freedraw)
|
||||||
displaymm('e', vid.xres-8, 8+fs, 2, vid.fsize, XLAT("e = edit this"), 16);
|
displaymm('e', vid.xres-8, 8+fs, 2, vid.fsize, XLAT("e = edit this"), 16);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1933,9 +2210,14 @@ namespace mapeditor {
|
|||||||
if(mkuni == 'g')
|
if(mkuni == 'g')
|
||||||
coldcenter = ccenter, ccenter = mh, clickused = true;
|
coldcenter = ccenter, ccenter = mh, clickused = true;
|
||||||
|
|
||||||
if(uni == 'd' || uni == 'l' || uni == 'c')
|
if(uni == 'd' || uni == 'l' || uni == 'c' || uni == 'e')
|
||||||
mousekey = uni;
|
mousekey = uni;
|
||||||
|
|
||||||
|
if(drawing_tool) {
|
||||||
|
if(sym == SDLK_F2) save_level();
|
||||||
|
if(sym == SDLK_F3) load_level();
|
||||||
|
}
|
||||||
|
|
||||||
if(uni == ' ' && (cheater || autocheat)) {
|
if(uni == ' ' && (cheater || autocheat)) {
|
||||||
popScreen();
|
popScreen();
|
||||||
pushScreen(showMapEditor);
|
pushScreen(showMapEditor);
|
||||||
@ -2001,32 +2283,54 @@ namespace mapeditor {
|
|||||||
|
|
||||||
if(sym == SDLK_F10) popScreen();
|
if(sym == SDLK_F10) popScreen();
|
||||||
|
|
||||||
#if CAP_TEXTURE
|
(void)clickused;
|
||||||
if(texture::config.tstate == texture::tsActive) {
|
|
||||||
|
|
||||||
|
bool freedraw = drawing_tool;
|
||||||
|
#if CAP_TEXTURE
|
||||||
|
bool intexture = texture::config.tstate == texture::tsActive;
|
||||||
|
freedraw |= intexture;
|
||||||
|
#else
|
||||||
|
always_false intexture;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(freedraw) {
|
||||||
|
|
||||||
int tcolor = (texture::config.paint_color >> 8) | ((texture::config.paint_color & 0xFF) << 24);
|
int tcolor = (texture::config.paint_color >> 8) | ((texture::config.paint_color & 0xFF) << 24);
|
||||||
|
|
||||||
if(uni == '-' && !clickused) {
|
if(uni == '-' && !clickused) {
|
||||||
if(mousekey == 'l' || mousekey == 'c') {
|
if(mousekey == 'e') {
|
||||||
|
dt_erase(mouseh);
|
||||||
|
clickused = true;
|
||||||
|
}
|
||||||
|
else if(mousekey == 'l' || mousekey == 'c') {
|
||||||
if(!holdmouse) lstart = mouseh, lstartcell = mouseover, holdmouse = true;
|
if(!holdmouse) lstart = mouseh, lstartcell = mouseover, holdmouse = true;
|
||||||
}
|
}
|
||||||
else {
|
else if(intexture) {
|
||||||
if(!holdmouse) texture::config.data.undoLock();
|
if(!holdmouse) texture::config.data.undoLock();
|
||||||
texture::drawPixel(mouseover, mouseh, tcolor);
|
texture::drawPixel(mouseover, mouseh, tcolor);
|
||||||
holdmouse = true; lstartcell = NULL;
|
holdmouse = true; lstartcell = NULL;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
dt_add_free(mouseh);
|
||||||
|
holdmouse = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sym == PSEUDOKEY_RELEASE) {
|
if(sym == PSEUDOKEY_RELEASE) {
|
||||||
printf("release\n");
|
printf("release\n");
|
||||||
if(mousekey == 'l') {
|
if(mousekey == 'l' && intexture) {
|
||||||
texture::config.data.undoLock();
|
texture::config.data.undoLock();
|
||||||
texture::where = mouseover;
|
texture::where = mouseover;
|
||||||
texture::drawPixel(mouseover, mouseh, tcolor);
|
texture::drawPixel(mouseover, mouseh, tcolor);
|
||||||
texture::drawLine(mouseh, lstart, tcolor);
|
texture::drawLine(mouseh, lstart, tcolor);
|
||||||
lstartcell = NULL;
|
lstartcell = NULL;
|
||||||
}
|
}
|
||||||
if(mousekey == 'c') {
|
else if(mousekey == 'l') {
|
||||||
|
dt_add_line(mouseh, lstart, 10);
|
||||||
|
lstartcell = NULL;
|
||||||
|
}
|
||||||
|
else if(mousekey == 'c' && intexture) {
|
||||||
texture::config.data.undoLock();
|
texture::config.data.undoLock();
|
||||||
ld rad = hdist(lstart, mouseh);
|
ld rad = hdist(lstart, mouseh);
|
||||||
int circp = int(1 + 3 * (circlelength(rad) / texture::penwidth));
|
int circp = int(1 + 3 * (circlelength(rad) / texture::penwidth));
|
||||||
@ -2037,6 +2341,14 @@ namespace mapeditor {
|
|||||||
texture::drawPixel(T * xspinpush0(2 * M_PI * i / circp, rad), tcolor);
|
texture::drawPixel(T * xspinpush0(2 * M_PI * i / circp, rad), tcolor);
|
||||||
lstartcell = NULL;
|
lstartcell = NULL;
|
||||||
}
|
}
|
||||||
|
else if(mousekey == 'c') {
|
||||||
|
dt_add_circle(lstart, mouseh);
|
||||||
|
lstartcell = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cfree = nullptr;
|
||||||
|
cfree_at = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(uni >= 1000 && uni < 1010)
|
if(uni >= 1000 && uni < 1010)
|
||||||
@ -2057,13 +2369,16 @@ namespace mapeditor {
|
|||||||
dialog::openColorDialog(texture::config.paint_color, texture_colors);
|
dialog::openColorDialog(texture::config.paint_color, texture_colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(uni == 'f') {
|
||||||
|
if(dtfill == texture::config.paint_color)
|
||||||
|
dtfill = 0;
|
||||||
|
else
|
||||||
|
dtfill = texture::config.paint_color;
|
||||||
|
}
|
||||||
|
|
||||||
if(uni == 'b')
|
if(uni == 'b')
|
||||||
dialog::editNumber(texture::penwidth, 0, 0.1, 0.005, 0.02, XLAT("brush size"), XLAT("brush size"));
|
dialog::editNumber(texture::penwidth, 0, 0.1, 0.005, 0.02, XLAT("brush size"), XLAT("brush size"));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
(void)clickused;
|
|
||||||
if(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
else {
|
else {
|
||||||
dslayer %= USERLAYERS;
|
dslayer %= USERLAYERS;
|
||||||
@ -2137,6 +2452,9 @@ namespace mapeditor {
|
|||||||
if(!cheater) patterns::displaycodes = false;
|
if(!cheater) patterns::displaycodes = false;
|
||||||
if(!cheater) patterns::whichShape = 0;
|
if(!cheater) patterns::whichShape = 0;
|
||||||
modelcell.clear();
|
modelcell.clear();
|
||||||
|
mapeditor::dtshapes.clear();
|
||||||
|
mapeditor::cfree = nullptr;
|
||||||
|
mapeditor::cfree_at = nullptr;
|
||||||
}) +
|
}) +
|
||||||
addHook(hooks_removecells, 0, [] () {
|
addHook(hooks_removecells, 0, [] () {
|
||||||
modelcell.clear();
|
modelcell.clear();
|
||||||
@ -2159,8 +2477,7 @@ namespace mapeditor {
|
|||||||
|
|
||||||
transmatrix textrans;
|
transmatrix textrans;
|
||||||
|
|
||||||
#if CAP_TEXTURE
|
EX void queue_hcircle(transmatrix Ctr, ld radius) {
|
||||||
void queue_hcircle(transmatrix Ctr, ld radius) {
|
|
||||||
vector<hyperpoint> pts;
|
vector<hyperpoint> pts;
|
||||||
int circp = int(6 * pow(2, vid.linequality));
|
int circp = int(6 * pow(2, vid.linequality));
|
||||||
if(radius > 0.04) circp *= 2;
|
if(radius > 0.04) circp *= 2;
|
||||||
@ -2172,7 +2489,6 @@ namespace mapeditor {
|
|||||||
curvepoint(pts[0]);
|
curvepoint(pts[0]);
|
||||||
queuecurve(texture::config.paint_color, 0, PPR::LINE);
|
queuecurve(texture::config.paint_color, 0, PPR::LINE);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CAP_POLY
|
#if CAP_POLY
|
||||||
EX bool haveUserShape(eShapegroup group, int id) {
|
EX bool haveUserShape(eShapegroup group, int id) {
|
||||||
|
14
menus.cpp
14
menus.cpp
@ -433,13 +433,25 @@ EX void showCreative() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CAP_EDIT
|
#if CAP_EDIT
|
||||||
dialog::addItem(XLAT("vector graphics editor"), 'g');
|
dialog::addItem(XLAT("shape editor"), 'g');
|
||||||
dialog::add_action([] {
|
dialog::add_action([] {
|
||||||
|
mapeditor::drawing_tool = false;
|
||||||
pushScreen(mapeditor::showDrawEditor);
|
pushScreen(mapeditor::showDrawEditor);
|
||||||
mapeditor::initdraw(cwt.at);
|
mapeditor::initdraw(cwt.at);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CAP_EDIT
|
||||||
|
dialog::addItem(XLAT("drawing tool"), 'd');
|
||||||
|
dialog::add_action([] {
|
||||||
|
dialog::cheat_if_confirmed([] {
|
||||||
|
mapeditor::drawing_tool = true;
|
||||||
|
pushScreen(mapeditor::showDrawEditor);
|
||||||
|
mapeditor::initdraw(cwt.at);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
// display modes
|
// display modes
|
||||||
#if CAP_MODEL
|
#if CAP_MODEL
|
||||||
if(GDIM == 2) {
|
if(GDIM == 2) {
|
||||||
|
Loading…
Reference in New Issue
Block a user