@ -22,9 +22,11 @@ class TiledCollisionEditor : public olc::PixelGameEngine
bool dragging = false ;
bool dragTranslate = false ;
vf2d upperLeftDragOffset { } ;
Quadrilateral * highlightedQuad = nullptr ;
bool dragNewObj = false ;
vi2d upperLeftObjTile { } ;
vi2d lowerRightObjTile { } ;
Renderable circle ;
Renderable createNewButtonImg ;
@ -70,6 +72,7 @@ public:
createNewButton - > hotkey = Q ;
editButton = new ImageCheckBox { gui , editButtonImg , true , vf2d { 40.f , ScreenHeight ( ) - 36.f } , { 32.f , 32.f } , { 4 , 4 } , { 32 , 32 } } ;
editButton - > hotkey = E ;
return true ;
}
@ -77,6 +80,13 @@ public:
const Tileset & tileset = tilesets [ activeTileset ] ;
if ( selectedObj . length ( ) > 0 ) {
if ( GetKey ( DEL ) . bPressed ) {
tilesets [ activeTileset ] . objects . erase ( selectedObj ) ;
selectedObj = " " ;
return ;
}
for ( int y = 0 ; y < tileset . tilecount / tileset . columns ; y + + ) {
for ( int x = 0 ; x < tileset . columns ; x + + ) {
if ( ! geom2d : : contains ( tileset . objects . at ( selectedObj ) . bounds , vf2d { float ( x * tileset . tilewidth ) + tileset . tilewidth / 2 , float ( y * tileset . tileheight ) + tileset . tileheight / 2 } ) ) {
@ -117,36 +127,25 @@ public:
}
if ( editButton - > bChecked ) {
if ( GetMouse ( Mouse : : LEFT ) . bPressed ) {
if ( highlightedQuad ! = nullptr ) {
# pragma region Select a point on a collision quad.
for ( const Quadrilateral & quad : obj . collisionTiles ) {
for ( size_t pointInd = 0 ; const vf2d & point : quad ) {
for ( size_t pointInd = 0 ; const vf2d & point : * highlightedQuad ) {
if ( geom2d : : line < float > ( point , view . ScreenToWorld ( GetMousePos ( ) ) ) . length ( ) < 4 ) {
if ( GetMouse ( Mouse : : LEFT ) . bPressed ) {
editingPoint = pointInd ;
editingQuad = const_cast < Quadrilateral * > ( & quad ) ;
originalQuad = quad ;
}
editingQuad = highlightedQuad ;
originalQuad = * highlightedQuad ;
goto exitCollisionCheck ;
}
pointInd + + ;
}
}
# pragma endregion
for ( const Quadrilateral & quad : obj . collisionTiles ) {
std : : array < geom2d : : triangle < float > , 2 > collisionTris {
geom2d : : triangle < float > { quad [ 0 ] , quad [ 1 ] , quad [ 2 ] } ,
geom2d : : triangle < float > { quad [ 0 ] , quad [ 2 ] , quad [ 3 ] } ,
} ;
for ( geom2d : : triangle < float > & tri : collisionTris ) {
if ( geom2d : : overlaps ( tri , geom2d : : circle < float > ( view . ScreenToWorld ( GetMousePos ( ) ) , 3.f ) ) ) {
dragTranslate = true ;
editingQuad = const_cast < Quadrilateral * > ( & quad ) ;
upperLeftDragOffset = GetSnapPoint ( ) - quad [ 0 ] ;
editingQuad = highlightedQuad ;
upperLeftDragOffset = GetSnapPoint ( ) - ( * highlightedQuad ) [ 0 ] ;
originalQuad = * editingQuad ;
goto exitCollisionCheck ;
}
}
}
exitCollisionCheck :
if ( EditingQuad & & ! dragging ) {
( * editingQuad ) [ editingPoint ] = GetSnapPoint ( ) ;
@ -174,23 +173,8 @@ public:
}
if ( GetMouse ( Mouse : : RIGHT ) . bPressed & & ! EditingQuad & & ! dragTranslate ) {
std : : vector < Quadrilateral * > quadsToBeRemoved ;
for ( const Quadrilateral & quad : obj . collisionTiles ) {
std : : array < geom2d : : triangle < float > , 2 > collisionTris {
geom2d : : triangle < float > { quad [ 0 ] , quad [ 1 ] , quad [ 2 ] } ,
geom2d : : triangle < float > { quad [ 0 ] , quad [ 2 ] , quad [ 3 ] } ,
} ;
for ( geom2d : : triangle < float > & tri : collisionTris ) {
if ( geom2d : : overlaps ( tri , geom2d : : circle < float > ( view . ScreenToWorld ( GetMousePos ( ) ) , 3.f ) ) ) {
//Delete this quad, the mouse is overlapping it!
quadsToBeRemoved . push_back ( const_cast < Quadrilateral * > ( & quad ) ) ;
break ;
}
}
}
for ( Quadrilateral * quad : quadsToBeRemoved ) {
std : : erase_if ( tilesets [ activeTileset ] . objects [ selectedObj ] . collisionTiles , [ & ] ( Quadrilateral & q ) { return & q = = quad ; } ) ;
if ( highlightedQuad ! = nullptr ) {
std : : erase_if ( tilesets [ activeTileset ] . objects [ selectedObj ] . collisionTiles , [ & ] ( Quadrilateral & q ) { return & q = = highlightedQuad ; } ) ;
}
}
@ -215,18 +199,26 @@ public:
void NewObjectUpdate ( ) {
const Tileset & tileset = tilesets [ activeTileset ] ;
if ( GetMouse ( Mouse : : LEFT ) . bPressed ) {
vf2d worldCoords = view . ScreenToWorld ( GetMousePos ( ) ) ;
upperLeftObjTile = vi2d { int ( round ( worldCoords . x / tileset . tilewidth ) * tileset . tilewidth ) , int ( round ( worldCoords . y / tileset . tileheight ) * tileset . tileheight ) } ;
dragNewObj = true ;
}
if ( GetMouse ( Mouse : : LEFT ) . bReleased ) {
dragNewObj = false ;
vf2d worldCoords = view . ScreenToWorld ( GetMousePos ( ) ) ;
vi2d lowerRightObjTile = vi2d { int ( round ( worldCoords . x / tileset . tilewidth ) * tileset . tilewidth ) , int ( round ( worldCoords . y / tileset . tileheight ) * tileset . tileheight ) } ;
vi2d newUpperLeftTile = upperLeftObjTile ;
vi2d newLowerRightTile = lowerRightObjTile ;
geom2d : : rect < int > newObjRect { upperLeftObjTile , lowerRightObjTile - upperLeftObjTile } ;
if ( worldCoords . x < upperLeftObjTile . x ) {
newLowerRightTile . x = int ( floor ( worldCoords . x / tileset . tilewidth ) * tileset . tilewidth ) ;
std : : swap ( newUpperLeftTile . x , newLowerRightTile . x ) ;
}
if ( worldCoords . y < upperLeftObjTile . y ) {
newLowerRightTile . y = int ( floor ( worldCoords . y / tileset . tileheight ) * tileset . tileheight ) ;
std : : swap ( newUpperLeftTile . y , newLowerRightTile . y ) ;
}
if ( newLowerRightTile . x = = newUpperLeftTile . x ) newLowerRightTile . x + = tileset . tilewidth ;
if ( newLowerRightTile . y = = newUpperLeftTile . y ) newLowerRightTile . y + = tileset . tileheight ;
geom2d : : rect < int > newObjRect { newUpperLeftTile , newLowerRightTile - newUpperLeftTile } ;
const Tileset & tileset = tilesets [ activeTileset ] ;
//Check for intersection with other objects, if found then we deny creating this object this way.
@ -244,10 +236,10 @@ public:
TilesetObject & newObj = tilesets [ activeTileset ] . objects [ objName ] ;
newObj . name = objName ;
for ( int y = 0 ; y < newObjRect . size . y ; y + + ) {
for ( int x = 0 ; x < newObjRect . size . x ; x + + ) {
int tileX = upperLeftObj Tile. x / tileset . tilewidth + x ;
int tileY = upperLeftObj Tile. y / tileset . tileheight + y ;
for ( int y = 0 ; y < newObjRect . size . y / tileset . tileheight ; y + + ) {
for ( int x = 0 ; x < newObjRect . size . x / tileset . tilewidth ; x + + ) {
int tileX = newUpperLeft Tile. x / tileset . tilewidth + x ;
int tileY = newUpperLeft Tile. y / tileset . tileheight + y ;
int tileID = tileY * tileset . columns + tileX ;
newObj . AddTile ( tileset , tileID ) ;
}
@ -292,6 +284,13 @@ public:
if ( editButton - > bPressed ) createNewButton - > bChecked = false ;
if ( GetMouseY ( ) < ScreenHeight ( ) - 36 | | GetMouseX ( ) > 72 ) {
if ( selectedObj . length ( ) = = 0 ) {
if ( GetMouse ( Mouse : : LEFT ) . bPressed ) {
vf2d worldCoords = view . ScreenToWorld ( GetMousePos ( ) ) ;
upperLeftObjTile = vi2d { int ( floor ( worldCoords . x / tileset . tilewidth ) * tileset . tilewidth ) , int ( floor ( worldCoords . y / tileset . tileheight ) * tileset . tileheight ) } ;
dragNewObj = true ;
}
}
if ( ! dragNewObj ) {
Update ( ) ;
} else {
@ -308,7 +307,18 @@ public:
if ( selectedObj . length ( ) > 0 & & ! dragNewObj ) {
const TilesetObject & obj = tileset . objects . at ( selectedObj ) ;
Quadrilateral * highlightedQuad = nullptr ;
if ( highlightedQuad ! = nullptr ) {
std : : array < geom2d : : triangle < float > , 2 > collisionTris {
geom2d : : triangle < float > { ( * highlightedQuad ) [ 0 ] , ( * highlightedQuad ) [ 1 ] , ( * highlightedQuad ) [ 2 ] } ,
geom2d : : triangle < float > { ( * highlightedQuad ) [ 0 ] , ( * highlightedQuad ) [ 2 ] , ( * highlightedQuad ) [ 3 ] } ,
} ;
for ( geom2d : : triangle < float > & tri : collisionTris ) {
if ( geom2d : : overlaps ( tri , geom2d : : circle < float > ( view . ScreenToWorld ( GetMousePos ( ) ) , 3.f ) ) ) {
goto renderQuads ;
}
}
highlightedQuad = nullptr ;
} else {
for ( const Quadrilateral & quad : obj . collisionTiles ) {
std : : array < geom2d : : triangle < float > , 2 > collisionTris {
geom2d : : triangle < float > { quad [ 0 ] , quad [ 1 ] , quad [ 2 ] } ,
@ -321,6 +331,7 @@ public:
}
}
}
}
renderQuads :
for ( const Quadrilateral & quad : obj . collisionTiles ) {
std : : vector < vf2d > points ;
@ -347,11 +358,26 @@ public:
} else
if ( dragNewObj ) {
vf2d worldCoords = view . ScreenToWorld ( GetMousePos ( ) ) ;
vi2d lowerRightObjTile = vi2d { int ( round ( worldCoords . x / tileset . tilewidth ) * tileset . tilewidth ) , int ( round ( worldCoords . y / tileset . tileheight ) * tileset . tileheight ) } ;
lowerRightObjTile = vi2d { int ( ceil ( worldCoords . x / tileset . tilewidth ) * tileset . tilewidth ) , int ( ceil ( worldCoords . y / tileset . tileheight ) * tileset . tileheight ) } ;
vi2d newUpperLeftTile = upperLeftObjTile ;
vi2d newLowerRightTile = lowerRightObjTile ;
if ( worldCoords . x < upperLeftObjTile . x ) {
newLowerRightTile . x = int ( floor ( worldCoords . x / tileset . tilewidth ) * tileset . tilewidth ) ;
std : : swap ( newUpperLeftTile . x , newLowerRightTile . x ) ;
}
if ( worldCoords . y < upperLeftObjTile . y ) {
newLowerRightTile . y = int ( floor ( worldCoords . y / tileset . tileheight ) * tileset . tileheight ) ;
std : : swap ( newUpperLeftTile . y , newLowerRightTile . y ) ;
}
if ( newLowerRightTile . x = = newUpperLeftTile . x ) newLowerRightTile . x + = tileset . tilewidth ;
if ( newLowerRightTile . y = = newUpperLeftTile . y ) newLowerRightTile . y + = tileset . tileheight ;
Pixel overlayCol = { 0 , 0 , 255 , 160 } ;
geom2d : : rect < int > newObjRect { upperLeftObjTile , lowerRightObjTile - upperLeftObjTile } ;
geom2d : : rect < int > newObjRect { newUpperLeftTile , newLowerRightTile - newUpperLeft Tile} ;
for ( auto & [ name , obj ] : tileset . objects ) {
geom2d : : rect < float > offsetBounds { obj . bounds . pos + vf2d { 0.5f , 0.5f } , obj . bounds . size - vf2d { 1.f , 1.f } } ;
@ -361,7 +387,7 @@ public:
}
}
view . FillRectDecal ( upperLeftObjTile , lowerRightObjTile - upperLeftObjTil e, overlayCol ) ;
view . FillRectDecal ( newObjRect . pos , newObjRect . siz e, overlayCol ) ;
}
for ( auto & [ objName , obj ] : tileset . objects ) {