/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at
golgotha_source@usa.net (Subject should have "GOLG" in it)
***********************************************************************/
#include "st_edit.hh"
#include "m1_info.hh"
#include "window/window.hh"
#include "gtext_load.hh"
#include "image/image.hh"
#include "max_object.hh"
#include "window/win_evt.hh"
#include "device/kernel.hh"
#include "render.hh"
#include "app/app.hh"
#include "window/wmanager.hh"
#include "gui/text_input.hh"
#include "tmanage.hh"
#define HANDLE_SIZE 3
#define SNAP_DISTANCE 5
i4_float m1_st_edit_window_class::twidth() const
{
return (texture)? texture->width()-0.0001 : 255.9999;
}
i4_float m1_st_edit_window_class::theight() const
{
return (texture)? texture->height()-0.0001 : 255.9999;
}
void m1_st_edit_window_class::get_point(int poly, int num, int &x, int &y)
{
if (m1_info.obj)
{
g1_quad_class *q=m1_info.obj->quad+poly;
float tw=twidth(), th=theight();
x=(int)(q->u[num] * tw);
y=(int)(q->v[num] * th);
}
}
void m1_st_edit_window_class::draw(i4_draw_context_class &context)
{
local_image->clear(0, context);
if (texture)
texture->put_image(local_image, 0,0, context);
if (m1_info.obj)
{
w32 c=0x0000ff; //(254<<16)|(2<<8)|166;
int x1,y1,x2,y2;
for (int j=0; jnum_quad; j++)
{
if (m1_info.obj->quad[j].get_flags(g1_quad_class::SELECTED))
{
int i;
g1_quad_class *q=&m1_info.obj->quad[j];
get_point(j,0,x2,y2);
for (i=q->num_verts()-1; i>=0; i--)
{
get_point(j,i,x1,y1);
local_image->line(x1,y1,x2,y2, c, context);
x2 = x1; y2 = y1;
}
for (i=0; inum_verts(); i++)
{
int x,y;
get_point(j,i,x,y);
if (m1_info.obj->get_poly_vert_flag(j,1<bar(x-2,y-2,x+2,y+2, 0xffff00, context);
else
local_image->bar(x-2,y-2,x+2,y+2, 0x808080, context);
}
}
}
if (preselect_x>=0)
local_image->bar(preselect_x-2,preselect_y-2,preselect_x+2,preselect_y+2, 0xff00ff, context);
}
}
void m1_st_edit_window_class::drag_points(int xc, int yc)
{
m1_poly_object_class *obj=m1_info.obj;
if (!obj) return;
float tw=twidth(), th=theight();
float u_change=xc/tw, v_change=yc/th;
i4_bool change=i4_F;
for (int i=0; inum_quad; i++)
{
if (obj->quad[i].get_flags(g1_quad_class::SELECTED))
{
for (int j=0; jquad[i].num_verts(); j++)
{
if (obj->get_poly_vert_flag(i, 1<quad[i].u[j]+=u_change;
if (obj->quad[i].u[j]<0) obj->quad[i].u[j]=0;
if (obj->quad[i].u[j]>1) obj->quad[i].u[j]=1;
obj->quad[i].v[j]+=v_change;
if (obj->quad[i].v[j]<0) obj->quad[i].v[j]=0;
if (obj->quad[i].v[j]>1) obj->quad[i].v[j]=1;
change=i4_T;
}
}
}
}
if (change)
{
obj->calc_texture_scales();
request_redraw(i4_F);
if (m1_render_window.get())
m1_render_window->request_redraw(i4_F);
}
}
i4_bool m1_st_edit_window_class::verts_are_selected()
{
if (!m1_info.obj)
return 0;
for (int j=0; jnum_quad; j++)
if (m1_info.obj->quad[j].get_flags(g1_quad_class::SELECTED))
{
for (int i=0; iquad[j].num_verts(); i++)
if (m1_info.obj->get_poly_vert_flag(j,1<get_window_manager()->shift_pressed())
{
for (int j=0; jnum_quad; j++)
for (int i=0; i<4; i++)
obj->set_poly_vert_flag(j, 1<num_quad; j++)
{
g1_quad_class *q=obj->quad+j;
if (q->get_flags(g1_quad_class::SELECTED))
for (int i=0; inum_verts(); i++)
if (q->vertex_ref[i] == point)
obj->set_poly_vert_flag(j, 1<=0)
for (int j=0; jnum_quad; j++)
if (m1_info.obj->quad[j].get_flags(g1_quad_class::SELECTED))
{
for (int i=0; iquad[j].num_verts(); i++)
if (m1_info.obj->quad[j].vertex_ref[i] == m1_info.preselect_point)
get_point(j,i,preselect_x,preselect_y);
}
if (preselect_x!=old_px || preselect_y!=old_py)
request_redraw();
}
void m1_st_edit_window_class::change_current_texture(i4_const_str new_name)
{
if (m1_info.obj)
{
i4_file_class *fp=i4_open(new_name);
if (!fp) return;
delete fp;
int i;
for (i=0; inum_quad; i++)
if (m1_info.obj->quad[i].get_flags(g1_quad_class::SELECTED))
{
delete m1_info.obj->texture_names[i];
m1_info.obj->texture_names[i]=new i4_str(new_name);
}
m1_info.texture_list_changed();
}
}
void m1_st_edit_window_class::receive_event(i4_event *ev)
{
int pre_grab = grab;
m1_poly_object_class *obj=m1_info.obj;
if (!obj)
return ;
switch (ev->type())
{
case i4_event::WINDOW_MESSAGE:
{
CAST_PTR(wev, i4_window_message_class, ev);
if (wev->sub_type==i4_window_message_class::GOT_DROP)
i4_kernel.send_event(tname_edit, ev);
} break;
case i4_event::OBJECT_MESSAGE :
{
CAST_PTR(tc, i4_text_change_notify_event, ev);
if (tc->object==tname_edit && tc->new_text && m1_info.obj)
{
i4_file_class *fp=i4_open(*tc->new_text);
if (!fp) return;
delete fp;
int i;
for (i=0; inum_quad; i++)
if (m1_info.obj->quad[i].get_flags(g1_quad_class::SELECTED))
m1_info.obj->texture_names[i]=new i4_str(*tc->new_text);
m1_info.texture_list_changed();
}
} break;
case i4_event::MOUSE_BUTTON_DOWN :
{
CAST_PTR(bev, i4_mouse_button_down_event_class, ev);
if (bev->left()) grab |= LEFT;
if (bev->right()) grab |= RIGHT;
if (bev->center()) grab |= MIDDLE;
i4_window_request_key_grab_class kgrab(this);
i4_kernel.send_event(parent, &kgrab);
i4_bool clear_old=i4_T;
int sel_poly=-1, sel_vert=-1;
if (bev->left() && obj)
{
for (int j=0; jnum_quad; j++)
{
g1_quad_class *q=obj->quad+j;
if (q->get_flags(g1_quad_class::SELECTED))
{
for (int i=0; inum_verts(); i++)
{
int x,y;
get_point(j,i,x,y);
if (abs(bev->x-x)y-y)get_poly_vert_flag(j, 1<set_poly_vert_flag(j, 1<get_window_manager()->shift_pressed())
{
for (int j=0; jnum_quad; j++)
for (int i=0; i<4; i++)
obj->set_poly_vert_flag(j, 1<set_poly_vert_flag(sel_poly, 1<left()) grab &= ~LEFT;
if (bev->right()) grab &= ~RIGHT;
if (bev->center()) grab &= ~MIDDLE;
} break;
case i4_event::MOUSE_MOVE :
{
CAST_PTR(mev, i4_mouse_move_event_class, ev);
int old_px = preselect_x, old_py = preselect_y;
preselect_x = -1;
if (m1_info.obj)
{
if (grab && verts_are_selected())
{
int snap_x = mev->x, snap_y = mev->y;
for (int j=0; jnum_quad; j++)
{
g1_quad_class *q=m1_info.obj->quad+j;
if (q->get_flags(g1_quad_class::SELECTED))
{
for (int i=0; inum_verts(); i++)
{
if (!m1_info.obj->get_poly_vert_flag(j,1<x-x)y-y)lx, snap_y+snap_off_y-mev->ly);
snap_off_x = mev->x - snap_x;
snap_off_y = mev->y - snap_y;
}
else
{
for (int j=0; jnum_quad; j++)
{
g1_quad_class *q=m1_info.obj->quad+j;
if (q->get_flags(g1_quad_class::SELECTED))
{
for (int i=0; inum_verts(); i++)
{
int x,y;
get_point(j,i,x,y);
if (abs(mev->x-x)y-y)x - preselect_x;
snap_off_y = mev->y - preselect_y;
}
}
}
}
}
if (old_px!=preselect_x || old_py!=preselect_y)
request_redraw();
}
} break;
}
if (!pre_grab && grab)
{
i4_window_request_mouse_grab_class grab_ev(this);
i4_kernel.send_event(parent,&grab_ev);
}
if (pre_grab && !grab)
{
i4_window_request_mouse_ungrab_class grab_ev(this);
i4_kernel.send_event(parent,&grab_ev);
}
}
void m1_st_edit_window_class::edit_poly_changed()
{
if (texture)
delete texture;
texture=0;
if (m1_info.obj)
{
m1_poly_object_class *obj=m1_info.obj;
int sel_poly=-1;
for (int j=0; jnum_quad; j++)
if (obj->quad[j].get_flags(g1_quad_class::SELECTED))
{
if (sel_poly==-1)
sel_poly=j;
else if (sel_poly>=0)
if (!(*obj->texture_names[sel_poly] == *obj->texture_names[j]))
sel_poly=-2;
}
if (sel_poly==-1)
tname_edit->change_text("");
else if (sel_poly==-2)
tname_edit->change_text("");
else
{
i4_image_class *im[10];
int t=r1_load_gtext(r1_get_texture_id(*obj->texture_names[sel_poly]), im);
for (int i=1; ichange_text(*obj->texture_names[sel_poly]);
else
tname_edit->change_text("");
}
}
request_redraw(i4_F);
}
m1_st_edit_window_class::m1_st_edit_window_class(w16 w, w16 h,
i4_text_input_class *tname_edit)
: i4_window_class(w,h),
tname_edit(tname_edit)
{
texture=0;
dragging=i4_F;
preselect_x = -1;
grab=0;
}
i4_event_handler_reference_class m1_st_edit;