Clean up brush code

This commit is contained in:
mniip 2023-02-19 01:39:32 +01:00 committed by mniip
parent 18a4407166
commit 515df765e4
22 changed files with 505 additions and 497 deletions

View File

@ -3,52 +3,41 @@
#include "Misc.h"
#include <cmath>
BitmapBrush::BitmapBrush(unsigned char *newBitmap, ui::Point rectSize_):
Brush(ui::Point(0, 0)),
BitmapBrush::BitmapBrush(ui::Point inputSize, unsigned char const *inputBitmap):
Brush(),
radius(inputSize / 2),
origSize(0, 0)
{
ui::Point newSize = rectSize_;
ui::Point newSize = inputSize;
//Ensure the rect has odd dimensions so we can pull an integer radius with a 1x1 centre
if(!(newSize.X % 2))
if (!(newSize.X % 2))
newSize.X += 1;
if(!(newSize.Y % 2))
if (!(newSize.Y % 2))
newSize.Y += 1;
radius = (newSize-ui::Point(1, 1))/2;
size = newSize;
origSize = size;
origBitmap = new unsigned char[size.X*size.Y];
std::fill(origBitmap, origBitmap+(size.X*size.Y), 0);
for(int y = 0; y < rectSize_.Y; y++)
{
for(int x = 0; x < rectSize_.X; x++)
{
if(newBitmap[(y*rectSize_.X)+x] >= 128)
origBitmap[(y*size.X)+x] = newBitmap[(y*rectSize_.X)+x];
}
}
SetRadius(radius);
origSize = newSize;
origBitmap = std::make_unique<unsigned char []>(newSize.X * newSize.Y);
std::fill(&origBitmap[0], &origBitmap[newSize.X * newSize.Y], 0);
for (int y = 0; y < inputSize.Y; y++)
for (int x = 0; x < inputSize.X; x++)
origBitmap[x + y * newSize.X] = inputBitmap[x + y * inputSize.X];
};
void BitmapBrush::GenerateBitmap()
std::pair<ui::Point, std::unique_ptr<unsigned char []>> BitmapBrush::GenerateBitmap() const
{
if(origBitmap)
{
delete[] bitmap;
bitmap = new unsigned char[size.X*size.Y];
if(size == origSize)
std::copy(origBitmap, origBitmap+(origSize.X*origSize.Y), bitmap);
ui::Point size = radius * 2 + 1;
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
if (size == origSize)
std::copy(&origBitmap[0], &origBitmap[origSize.X * origSize.Y], &bitmap[0]);
else
{
//Bilinear interpolation
float factorX = ((float)origSize.X)/((float)size.X);
float factorY = ((float)origSize.Y)/((float)size.Y);
for(int y = 0; y < size.Y; y++)
for (int y = 0; y < size.Y; y++)
{
for(int x = 0; x < size.X; x++)
for (int x = 0; x < size.X; x++)
{
float originalY = ((float)y)*factorY;
float originalX = ((float)x)*factorX;
@ -69,10 +58,5 @@ void BitmapBrush::GenerateBitmap()
}
}
}
}
}
BitmapBrush::~BitmapBrush()
{
delete[] origBitmap;
return std::make_pair(radius, std::move(bitmap));
}

View File

@ -11,11 +11,24 @@
class BitmapBrush: public Brush
{
protected:
ui::Point radius;
ui::Point origSize;
unsigned char * origBitmap;
// 2D array with coords [0, origSize.X) by [0, origSize.Y)
std::unique_ptr<unsigned char []> origBitmap;
public:
BitmapBrush(unsigned char *newBitmap, ui::Point rectSize);
void GenerateBitmap() override;
virtual ~BitmapBrush();
BitmapBrush(ui::Point size, unsigned char const *bitmap);
virtual ~BitmapBrush() override = default;
std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const override;
ui::Point GetRadius() const override
{
return radius;
}
void SetRadius(ui::Point radius) override
{
this->radius = radius;
InvalidateCache();
}
};

View File

@ -1,123 +1,117 @@
#include "Brush.h"
#include "graphics/Renderer.h"
Brush::Brush(ui::Point size_):
outline(NULL),
bitmap(NULL),
size(0, 0),
radius(0, 0)
void Brush::InvalidateCache()
{
SetRadius(size_);
};
Brush::~Brush()
{
delete[] bitmap;
delete[] outline;
size = ui::Point(0, 0);
bitmap.reset();
outline.reset();
}
void Brush::updateOutline()
void Brush::ensureBitmap() const
{
if(!bitmap)
GenerateBitmap();
if(!bitmap)
if (bitmap)
return;
delete[] outline;
outline = new unsigned char[size.X*size.Y];
for(int x = 0; x < size.X; x++)
auto pair = GenerateBitmap();
size = pair.first;
bitmap = std::move(pair.second);
}
void Brush::ensureOutline() const
{
if (outline)
return;
ensureBitmap();
ui::Point bounds = size * 2 + 1;
outline = std::make_unique<unsigned char []>(bounds.X * bounds.Y);
for (int j = 0; j < bounds.Y; j++)
for (int i = 0; i < bounds.X; i++)
{
for(int y = 0; y < size.Y; y++)
bool value = false;
if (bitmap[i + j * bounds.X])
{
if(bitmap[y*size.X+x] && (!y || !x || x == size.X-1 || y == size.Y-1 || !bitmap[y*size.X+(x+1)] || !bitmap[y*size.X+(x-1)] || !bitmap[(y-1)*size.X+x] || !bitmap[(y+1)*size.X+x]))
{
outline[y*size.X+x] = 255;
if (i == 0 || j == 0 || i == bounds.X - 1 || j == bounds.Y - 1)
value = true;
else if (!bitmap[(i + 1) + j * bounds.X])
value = true;
else if (!bitmap[(i - 1) + j * bounds.X])
value = true;
else if (!bitmap[i + (j + 1) * bounds.X])
value = true;
else if (!bitmap[i + (j - 1) * bounds.X])
value = true;
}
outline[i + j * bounds.X] = value ? 0xFF : 0;
}
}
void Brush::AdjustSize(int delta, bool logarithmic, bool keepX, bool keepY)
{
if (keepX && keepY)
return;
ui::Point newSize(0, 0);
ui::Point oldSize = GetRadius();
if (logarithmic)
newSize = oldSize + ui::Point(delta * std::max(oldSize.X / 5, 1), delta * std::max(oldSize.Y / 5, 1));
else
outline[y*size.X+x] = 0;
}
}
newSize = oldSize + ui::Point(delta, delta);
if (newSize.X < 0)
newSize.X = 0;
if (newSize.Y < 0)
newSize.Y = 0;
if (newSize.X > 200)
newSize.X = 200;
if (newSize.Y > 200)
newSize.Y = 200;
if (keepY)
SetRadius(ui::Point(newSize.X, oldSize.Y));
else if (keepX)
SetRadius(ui::Point(oldSize.X, newSize.Y));
else
SetRadius(newSize);
}
void Brush::SetRadius(ui::Point radius)
{
this->radius = radius;
this->size = radius+radius+ui::Point(1, 1);
GenerateBitmap();
updateOutline();
}
void Brush::GenerateBitmap()
{
delete[] bitmap;
bitmap = new unsigned char[size.X*size.Y];
for(int x = 0; x < size.X; x++)
{
for(int y = 0; y < size.Y; y++)
{
bitmap[(y*size.X)+x] = 255;
}
}
}
unsigned char *Brush::GetBitmap()
{
if(!bitmap)
GenerateBitmap();
return bitmap;
}
unsigned char *Brush::GetOutline()
{
if(!outline)
updateOutline();
if(!outline)
return NULL;
return outline;
}
void Brush::RenderRect(Renderer * ren, ui::Point position1, ui::Point position2)
void Brush::RenderRect(Renderer * ren, ui::Point position1, ui::Point position2) const
{
int width, height;
width = position2.X-position1.X;
height = position2.Y-position1.Y;
if(height<0)
if (height<0)
{
position1.Y += height;
height *= -1;
}
if(width<0)
if (width<0)
{
position1.X += width;
width *= -1;
}
ren->xor_line(position1.X, position1.Y, position1.X+width, position1.Y);
if(height>0){
if (height>0){
ren->xor_line(position1.X, position1.Y+height, position1.X+width, position1.Y+height);
if(height>1){
if (height>1){
ren->xor_line(position1.X+width, position1.Y+1, position1.X+width, position1.Y+height-1);
if(width>0)
if (width>0)
ren->xor_line(position1.X, position1.Y+1, position1.X, position1.Y+height-1);
}
}
}
void Brush::RenderLine(Renderer * ren, ui::Point position1, ui::Point position2)
void Brush::RenderLine(Renderer * ren, ui::Point position1, ui::Point position2) const
{
ren->xor_line(position1.X, position1.Y, position2.X, position2.Y);
}
void Brush::RenderPoint(Renderer * ren, ui::Point position)
void Brush::RenderPoint(Renderer * ren, ui::Point position) const
{
if(!outline)
updateOutline();
if(!outline)
return;
ren->xor_bitmap(outline, position.X-radius.X, position.Y-radius.Y, size.X, size.Y);
ensureOutline();
ren->xor_bitmap(&outline[0], position.X - size.X, position.Y - size.Y, 2 * size.X + 1, 2 * size.Y + 1);
}
void Brush::RenderFill(Renderer * ren, ui::Point position)
void Brush::RenderFill(Renderer * ren, ui::Point position) const
{
ren->xor_line(position.X-5, position.Y, position.X-1, position.Y);
ren->xor_line(position.X+5, position.Y, position.X+1, position.Y);

View File

@ -1,39 +1,90 @@
#pragma once
#include "gui/interface/Point.h"
#include <memory>
class Renderer;
class Brush
{
protected:
unsigned char * outline;
unsigned char * bitmap;
ui::Point size;
ui::Point radius;
void updateOutline();
public:
Brush(ui::Point size);
private:
ui::Point mutable size;
// 2D arrays indexed by coordinates from [-size.X, size.X] by [-size.Y, size.Y]
std::unique_ptr<unsigned char []> mutable bitmap;
std::unique_ptr<unsigned char []> mutable outline;
//Radius of the brush 0x0 - infxinf (Radius of 0x0 would be 1x1, radius of 1x1 would be 3x3)
ui::Point GetRadius()
void ensureBitmap() const;
void ensureOutline() const;
struct iterator
{
return radius;
Brush const &parent;
int x, y;
iterator &operator++()
{
do
{
if (++x > parent.size.X)
{
--y;
x = -parent.size.X;
}
} while (y >= -parent.size.Y && !parent.bitmap[x + parent.size.X + (y + parent.size.Y) * (2 * parent.size.X + 1)]);
return *this;
}
//Size of the brush bitmap mask, 1x1 - infxinf
ui::Point GetSize()
ui::Point operator*() const
{
return ui::Point(x, y);
}
bool operator!=(iterator other) const
{
return x != other.x || y != other.y;
}
public:
using difference_type = void;
using value_type = ui::Point;
using pointer = void;
using reference = void;
using iterator_category = std::forward_iterator_tag;
};
protected:
Brush():
size(0, 0),
bitmap(),
outline()
{
}
void InvalidateCache();
virtual std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const = 0;
public:
virtual ~Brush() = default;
virtual ui::Point GetRadius() const = 0;
virtual void SetRadius(ui::Point radius) = 0;
virtual void AdjustSize(int delta, bool logarithmic, bool keepX, bool keepY);
ui::Point GetSize() const
{
return size;
}
virtual void SetRadius(ui::Point radius);
virtual ~Brush();
virtual void RenderRect(Renderer * ren, ui::Point position1, ui::Point position2);
virtual void RenderLine(Renderer * ren, ui::Point position1, ui::Point position2);
virtual void RenderPoint(Renderer * ren, ui::Point position);
virtual void RenderFill(Renderer * ren, ui::Point position);
virtual void GenerateBitmap();
//Get a bitmap for drawing particles
unsigned char * GetBitmap();
unsigned char * GetOutline();
iterator begin() const
{
// bottom to top is the preferred order for Simulation::CreateParts
return ++iterator{*this, size.X, size.Y + 1};
}
iterator end() const
{
return iterator{*this, -size.X, -size.Y - 1};
}
void RenderRect(Renderer * ren, ui::Point position1, ui::Point position2) const;
void RenderLine(Renderer * ren, ui::Point position1, ui::Point position2) const;
void RenderPoint(Renderer * ren, ui::Point position) const;
void RenderFill(Renderer * ren, ui::Point position) const;
};

View File

@ -62,22 +62,22 @@ DecorationTool::~DecorationTool()
{
}
void DecorationTool::Draw(Simulation * sim, Brush * brush, ui::Point position)
void DecorationTool::Draw(Simulation * sim, Brush const &brush, ui::Point position)
{
sim->ApplyDecorationPoint(position.X, position.Y, Red, Green, Blue, Alpha, toolID, brush);
}
void DecorationTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging)
void DecorationTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging)
{
sim->ApplyDecorationLine(position1.X, position1.Y, position2.X, position2.Y, Red, Green, Blue, Alpha, toolID, brush);
}
void DecorationTool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2)
void DecorationTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2)
{
sim->ApplyDecorationBox(position1.X, position1.Y, position2.X, position2.Y, Red, Green, Blue, Alpha, toolID);
}
void DecorationTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position)
void DecorationTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position)
{
pixel loc = ren->vid[position.X+position.Y*WINDOWW];
if (toolID == DECO_CLEAR)

View File

@ -16,8 +16,8 @@ public:
DecorationTool(Renderer *ren_, int decoMode, String name, String description, int r, int g, int b, ByteString identifier);
virtual ~DecorationTool();
void Draw(Simulation * sim, Brush * brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) override;
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override;
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override;
};

View File

@ -4,20 +4,23 @@
class EllipseBrush: public Brush
{
ui::Point radius;
bool perfectCircle;
public:
EllipseBrush(ui::Point size, bool perfectCircle = true):
Brush(size)
EllipseBrush(ui::Point radius, bool perfectCircle = true):
Brush(),
radius(radius),
perfectCircle(perfectCircle)
{
this->perfectCircle = perfectCircle;
SetRadius(size);
}
virtual ~EllipseBrush() override = default;
void GenerateBitmap() override
std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const override
{
delete[] bitmap;
bitmap = new unsigned char[size.X*size.Y];
ui::Point size = radius * 2 + 1;
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
int rx = radius.X;
int ry = radius.Y;
@ -61,5 +64,17 @@ public:
bitmap[size.X/2] = 255;
bitmap[size.X*size.Y-size.X/2-1] = 255;
}
return std::make_pair(radius, std::move(bitmap));
}
ui::Point GetRadius() const override
{
return radius;
}
void SetRadius(ui::Point radius) override
{
this->radius = radius;
InvalidateCache();
}
};

View File

@ -285,37 +285,14 @@ void GameController::InvertAirSim()
}
void GameController::AdjustBrushSize(int delta, bool logarithmic, bool xAxis, bool yAxis)
void GameController::AdjustBrushSize(int delta, bool logarithmic, bool keepX, bool keepY)
{
if(xAxis && yAxis)
return;
ui::Point newSize(0, 0);
ui::Point oldSize = gameModel->GetBrush()->GetRadius();
if(logarithmic)
newSize = gameModel->GetBrush()->GetRadius() + ui::Point(delta * std::max(gameModel->GetBrush()->GetRadius().X / 5, 1), delta * std::max(gameModel->GetBrush()->GetRadius().Y / 5, 1));
else
newSize = gameModel->GetBrush()->GetRadius() + ui::Point(delta, delta);
if(newSize.X < 0)
newSize.X = 0;
if(newSize.Y < 0)
newSize.Y = 0;
if(newSize.X > 200)
newSize.X = 200;
if(newSize.Y > 200)
newSize.Y = 200;
if(xAxis)
SetBrushSize(ui::Point(newSize.X, oldSize.Y));
else if(yAxis)
SetBrushSize(ui::Point(oldSize.X, newSize.Y));
else
SetBrushSize(newSize);
gameModel->GetBrush().AdjustSize(delta, logarithmic, keepX, keepY);
}
void GameController::SetBrushSize(ui::Point newSize)
{
gameModel->GetBrush()->SetRadius(newSize);
gameModel->GetBrush().SetRadius(newSize);
}
void GameController::AdjustZoomSize(int delta, bool logarithmic)
@ -380,8 +357,8 @@ void GameController::DrawRect(int toolSelection, ui::Point point1, ui::Point poi
Simulation * sim = gameModel->GetSimulation();
Tool * activeTool = gameModel->GetActiveTool(toolSelection);
gameModel->SetLastTool(activeTool);
Brush * cBrush = gameModel->GetBrush();
if(!activeTool || !cBrush)
Brush &cBrush = gameModel->GetBrush();
if (!activeTool)
return;
activeTool->SetStrength(1.0f);
activeTool->DrawRect(sim, cBrush, point1, point2);
@ -392,8 +369,8 @@ void GameController::DrawLine(int toolSelection, ui::Point point1, ui::Point poi
Simulation * sim = gameModel->GetSimulation();
Tool * activeTool = gameModel->GetActiveTool(toolSelection);
gameModel->SetLastTool(activeTool);
Brush * cBrush = gameModel->GetBrush();
if(!activeTool || !cBrush)
Brush &cBrush = gameModel->GetBrush();
if (!activeTool)
return;
activeTool->SetStrength(1.0f);
activeTool->DrawLine(sim, cBrush, point1, point2);
@ -404,8 +381,8 @@ void GameController::DrawFill(int toolSelection, ui::Point point)
Simulation * sim = gameModel->GetSimulation();
Tool * activeTool = gameModel->GetActiveTool(toolSelection);
gameModel->SetLastTool(activeTool);
Brush * cBrush = gameModel->GetBrush();
if(!activeTool || !cBrush)
Brush &cBrush = gameModel->GetBrush();
if (!activeTool)
return;
activeTool->SetStrength(1.0f);
activeTool->DrawFill(sim, cBrush, point);
@ -416,8 +393,8 @@ void GameController::DrawPoints(int toolSelection, ui::Point oldPos, ui::Point n
Simulation * sim = gameModel->GetSimulation();
Tool * activeTool = gameModel->GetActiveTool(toolSelection);
gameModel->SetLastTool(activeTool);
Brush * cBrush = gameModel->GetBrush();
if (!activeTool || !cBrush)
Brush &cBrush = gameModel->GetBrush();
if (!activeTool)
{
return;
}
@ -464,8 +441,8 @@ void GameController::ToolClick(int toolSelection, ui::Point point)
{
Simulation * sim = gameModel->GetSimulation();
Tool * activeTool = gameModel->GetActiveTool(toolSelection);
Brush * cBrush = gameModel->GetBrush();
if(!activeTool || !cBrush)
Brush &cBrush = gameModel->GetBrush();
if (!activeTool)
return;
activeTool->Click(sim, cBrush, point);
}
@ -1481,9 +1458,9 @@ void GameController::Vote(int direction)
void GameController::ChangeBrush()
{
auto prev_size = gameModel->GetBrush()->GetRadius();
auto prev_size = gameModel->GetBrush().GetRadius();
gameModel->SetBrushID(gameModel->GetBrushID()+1);
gameModel->GetBrush()->SetRadius(prev_size);
gameModel->GetBrush().SetRadius(prev_size);
}
void GameController::ClearSim()

View File

@ -8,6 +8,7 @@
#include "GameView.h"
#include "Menu.h"
#include "Notification.h"
#include "RectangleBrush.h"
#include "TriangleBrush.h"
#include "QuickOptions.h"
#include "lua/CommandInterface.h"
@ -31,6 +32,7 @@
#include "gui/interface/Engine.h"
#include <iostream>
#include <algorithm>
#include <optional>
HistoryEntry::~HistoryEntry()
{
@ -183,10 +185,6 @@ GameModel::~GameModel()
{
delete *iter;
}
for (size_t i = 0; i < brushList.size(); i++)
{
delete brushList[i];
}
delete sim;
delete ren;
delete placeSave;
@ -464,18 +462,14 @@ void GameModel::BuildFavoritesMenu()
void GameModel::BuildBrushList()
{
bool hasStoredRadius = false;
ui::Point radius = ui::Point(0, 0);
std::optional<ui::Point> radius;
if (brushList.size())
{
radius = brushList[currentBrush]->GetRadius();
hasStoredRadius = true;
}
brushList.clear();
brushList.push_back(new EllipseBrush(ui::Point(4, 4), perfectCircle));
brushList.push_back(new Brush(ui::Point(4, 4)));
brushList.push_back(new TriangleBrush(ui::Point(4, 4)));
brushList.push_back(std::make_unique<EllipseBrush>(ui::Point(4, 4), perfectCircle));
brushList.push_back(std::make_unique<RectangleBrush>(ui::Point(4, 4)));
brushList.push_back(std::make_unique<TriangleBrush>(ui::Point(4, 4)));
//Load more from brushes folder
std::vector<ByteString> brushFiles = Platform::DirectorySearch(BRUSH_DIR, "", { ".ptb" });
@ -493,11 +487,11 @@ void GameModel::BuildBrushList()
std::cout << "Brushes: Skipping " << brushFiles[i] << ". Invalid bitmap size" << std::endl;
continue;
}
brushList.push_back(new BitmapBrush(reinterpret_cast<unsigned char *>(&brushData[0]), ui::Point(dimension, dimension)));
brushList.push_back(std::make_unique<BitmapBrush>(ui::Point(dimension, dimension), reinterpret_cast<unsigned char const *>(brushData.data())));
}
if (hasStoredRadius && (size_t)currentBrush < brushList.size())
brushList[currentBrush]->SetRadius(radius);
if (radius && (size_t)currentBrush < brushList.size())
brushList[currentBrush]->SetRadius(*radius);
notifyBrushChanged();
}
@ -813,12 +807,12 @@ void GameModel::SetVote(int direction)
}
}
Brush * GameModel::GetBrush()
Brush &GameModel::GetBrush()
{
return brushList[currentBrush];
return *brushList[currentBrush];
}
std::vector<Brush*> GameModel::GetBrushList()
std::vector<std::unique_ptr<Brush>> const &GameModel::GetBrushList()
{
return brushList;
}

View File

@ -61,7 +61,7 @@ private:
std::vector<QuickOption*> quickOptions;
int activeMenu;
int currentBrush;
std::vector<Brush *> brushList;
std::vector<std::unique_ptr<Brush>> brushList;
SaveInfo * currentSave;
SaveFile * currentFile;
Tool * lastTool;
@ -175,8 +175,8 @@ public:
std::vector<Tool*> GetToolList();
std::vector<Tool*> GetUnlistedTools();
Brush * GetBrush();
std::vector<Brush*> GetBrushList();
Brush &GetBrush();
std::vector<std::unique_ptr<Brush>> const &GetBrushList();
int GetBrushID();
void SetBrushID(int i);

View File

@ -918,7 +918,7 @@ void GameView::NotifySaveChanged(GameModel * sender)
void GameView::NotifyBrushChanged(GameModel * sender)
{
activeBrush = sender->GetBrush();
activeBrush = &sender->GetBrush();
}
ByteString GameView::TakeScreenshot(int captureUI, int fileType)
@ -1320,7 +1320,7 @@ void GameView::OnMouseWheel(int x, int y, int d)
}
else
{
c->AdjustBrushSize(d, false, shiftBehaviour, ctrlBehaviour);
c->AdjustBrushSize(d, false, ctrlBehaviour, shiftBehaviour);
}
}
@ -1575,13 +1575,13 @@ void GameView::OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl,
if(zoomEnabled && !zoomCursorFixed)
c->AdjustZoomSize(1, !alt);
else
c->AdjustBrushSize(1, !alt, shiftBehaviour, ctrlBehaviour);
c->AdjustBrushSize(1, !alt, ctrlBehaviour, shiftBehaviour);
break;
case SDL_SCANCODE_LEFTBRACKET:
if(zoomEnabled && !zoomCursorFixed)
c->AdjustZoomSize(-1, !alt);
else
c->AdjustBrushSize(-1, !alt, shiftBehaviour, ctrlBehaviour);
c->AdjustBrushSize(-1, !alt, ctrlBehaviour, shiftBehaviour);
break;
case SDL_SCANCODE_I:
if(ctrl)

View File

@ -78,7 +78,7 @@ private:
ui::Point currentPoint, lastPoint;
GameController * c;
Renderer * ren;
Brush * activeBrush;
Brush const *activeBrush;
//UI Elements
std::vector<ui::Button*> quickOptionButtons;

View File

@ -288,24 +288,21 @@ void PropertyTool::SetProperty(Simulation *sim, ui::Point position)
}
}
void PropertyTool::Draw(Simulation *sim, Brush *cBrush, ui::Point position)
void PropertyTool::Draw(Simulation *sim, Brush const &cBrush, ui::Point position)
{
if(cBrush)
for (ui::Point off : cBrush)
{
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
unsigned char *bitmap = cBrush->GetBitmap();
for(int y = 0; y < sizeY; y++)
for(int x = 0; x < sizeX; x++)
if(bitmap[(y*sizeX)+x] && (position.X+(x-radiusX) >= 0 && position.Y+(y-radiusY) >= 0 && position.X+(x-radiusX) < XRES && position.Y+(y-radiusY) < YRES))
SetProperty(sim, ui::Point(position.X+(x-radiusX), position.Y+(y-radiusY)));
ui::Point coords = position + off;
if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES)
SetProperty(sim, coords);
}
}
void PropertyTool::DrawLine(Simulation *sim, Brush *cBrush, ui::Point position, ui::Point position2, bool dragging)
void PropertyTool::DrawLine(Simulation *sim, Brush const &cBrush, ui::Point position, ui::Point position2, bool dragging)
{
int x1 = position.X, y1 = position.Y, x2 = position2.X, y2 = position2.Y;
bool reverseXY = abs(y2-y1) > abs(x2-x1);
int x, y, dx, dy, sy, rx = cBrush->GetRadius().X, ry = cBrush->GetRadius().Y;
int x, y, dx, dy, sy, rx = cBrush.GetRadius().X, ry = cBrush.GetRadius().Y;
float e = 0.0f, de;
if (reverseXY)
{
@ -355,7 +352,7 @@ void PropertyTool::DrawLine(Simulation *sim, Brush *cBrush, ui::Point position,
}
}
void PropertyTool::DrawRect(Simulation *sim, Brush *cBrush, ui::Point position, ui::Point position2)
void PropertyTool::DrawRect(Simulation *sim, Brush const &cBrush, ui::Point position, ui::Point position2)
{
int x1 = position.X, y1 = position.Y, x2 = position2.X, y2 = position2.Y;
int i, j;
@ -376,7 +373,7 @@ void PropertyTool::DrawRect(Simulation *sim, Brush *cBrush, ui::Point position,
SetProperty(sim, ui::Point(i, j));
}
void PropertyTool::DrawFill(Simulation *sim, Brush *cBrush, ui::Point position)
void PropertyTool::DrawFill(Simulation *sim, Brush const &cBrush, ui::Point position)
{
if (validProperty)
sim->flood_prop(position.X, position.Y, propOffset, propValue, propType);

View File

@ -0,0 +1,35 @@
#pragma once
#include "Brush.h"
class RectangleBrush: public Brush
{
ui::Point radius;
public:
RectangleBrush(ui::Point radius):
Brush(),
radius(radius)
{
}
virtual ~RectangleBrush() override = default;
std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const override
{
ui::Point size = radius * 2 + 1;
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
std::fill(&bitmap[0], &bitmap[size.X * size.Y], 0xFF);
return std::make_pair(radius, std::move(bitmap));
}
ui::Point GetRadius() const override
{
return radius;
}
void SetRadius(ui::Point radius) override
{
this->radius = radius;
InvalidateCache();
}
};

View File

@ -29,7 +29,7 @@ VideoBuffer * SampleTool::GetIcon(int toolID, int width, int height)
return newTexture;
}
void SampleTool::Draw(Simulation * sim, Brush * brush, ui::Point position)
void SampleTool::Draw(Simulation * sim, Brush const &brush, ui::Point position)
{
if(gameModel->GetColourSelectorVisibility())
{

View File

@ -242,7 +242,7 @@ VideoBuffer * SignTool::GetIcon(int toolID, int width, int height)
return newTexture;
}
void SignTool::Click(Simulation * sim, Brush * brush, ui::Point position)
void SignTool::Click(Simulation * sim, Brush const &brush, ui::Point position)
{
int signX, signY, signW, signH, signIndex = -1;
for (size_t i = 0; i < sim->signs.size(); i++)

View File

@ -37,17 +37,17 @@ String Tool::GetName() { return toolName; }
String Tool::GetDescription() { return toolDescription; }
Tool::~Tool() {}
void Tool::Click(Simulation * sim, Brush * brush, ui::Point position) { }
void Tool::Draw(Simulation * sim, Brush * brush, ui::Point position) {
void Tool::Click(Simulation * sim, Brush const &brush, ui::Point position) { }
void Tool::Draw(Simulation * sim, Brush const &brush, ui::Point position) {
sim->ToolBrush(position.X, position.Y, toolID, brush, strength);
}
void Tool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) {
void Tool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) {
sim->ToolLine(position1.X, position1.Y, position2.X, position2.Y, toolID, brush, strength);
}
void Tool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) {
void Tool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) {
sim->ToolBox(position1.X, position1.Y, position2.X, position2.Y, toolID, strength);
}
void Tool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) {}
void Tool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) {}
ElementTool::ElementTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int)):
@ -55,16 +55,16 @@ ElementTool::ElementTool(int id, String name, String description, int r, int g,
{
}
ElementTool::~ElementTool() {}
void ElementTool::Draw(Simulation * sim, Brush * brush, ui::Point position){
void ElementTool::Draw(Simulation * sim, Brush const &brush, ui::Point position){
sim->CreateParts(position.X, position.Y, toolID, brush);
}
void ElementTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) {
void ElementTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) {
sim->CreateLine(position1.X, position1.Y, position2.X, position2.Y, toolID, brush);
}
void ElementTool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) {
void ElementTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) {
sim->CreateBox(position1.X, position1.Y, position2.X, position2.Y, toolID);
}
void ElementTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) {
void ElementTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) {
sim->FloodParts(position.X, position.Y, toolID, -1);
}
@ -75,10 +75,10 @@ Tool(id, name, description, r, g, b, identifier, textureGen)
blocky = true;
}
WallTool::~WallTool() {}
void WallTool::Draw(Simulation * sim, Brush * brush, ui::Point position) {
sim->CreateWalls(position.X, position.Y, 1, 1, toolID, brush);
void WallTool::Draw(Simulation * sim, Brush const &brush, ui::Point position) {
sim->CreateWalls(position.X, position.Y, 1, 1, toolID, &brush);
}
void WallTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) {
void WallTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) {
int wallX = position1.X/CELL;
int wallY = position1.Y/CELL;
if(dragging == false && toolID == WL_FAN && sim->bmap[wallY][wallX]==WL_FAN)
@ -99,13 +99,13 @@ void WallTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui
}
else
{
sim->CreateWallLine(position1.X, position1.Y, position2.X, position2.Y, 1, 1, toolID, brush);
sim->CreateWallLine(position1.X, position1.Y, position2.X, position2.Y, 1, 1, toolID, &brush);
}
}
void WallTool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) {
void WallTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) {
sim->CreateWallBox(position1.X, position1.Y, position2.X, position2.Y, toolID);
}
void WallTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) {
void WallTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) {
if (toolID != WL_STREAM)
sim->FloodWalls(position.X, position.Y, toolID, -1);
}
@ -115,53 +115,41 @@ WindTool::WindTool(int id, String name, String description, int r, int g, int b,
{
}
void WindTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging)
void WindTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging)
{
int radiusX, radiusY, sizeX, sizeY;
float strength = dragging?0.01f:0.002f;
strength *= this->strength;
radiusX = brush->GetRadius().X;
radiusY = brush->GetRadius().Y;
sizeX = brush->GetSize().X;
sizeY = brush->GetSize().Y;
unsigned char *bitmap = brush->GetBitmap();
for(int y = 0; y < sizeY; y++)
for (ui::Point off : brush)
{
for(int x = 0; x < sizeX; x++)
ui::Point coords = position1 + off;
if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES)
{
if(bitmap[(y*sizeX)+x] && (position1.X+(x-radiusX) >= 0 && position1.Y+(y-radiusY) >= 0 && position1.X+(x-radiusX) < XRES && position1.Y+(y-radiusY) < YRES))
{
sim->vx[(position1.Y+(y-radiusY))/CELL][(position1.X+(x-radiusX))/CELL] += (position2.X-position1.X)*strength;
sim->vy[(position1.Y+(y-radiusY))/CELL][(position1.X+(x-radiusX))/CELL] += (position2.Y-position1.Y)*strength;
}
sim->vx[coords.Y / CELL][coords.X / CELL] += (position2 - position1).X * strength;
sim->vy[coords.Y / CELL][coords.X / CELL] += (position2 - position1).Y * strength;
}
}
}
void Element_LIGH_Tool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging)
void Element_LIGH_Tool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging)
{
if (dragging)
sim->CreateParts(position1.X, position1.Y, brush->GetRadius().X, brush->GetRadius().Y, PT_LIGH);
sim->CreateParts(position1.X, position1.Y, brush.GetRadius().X, brush.GetRadius().Y, PT_LIGH);
}
void Element_TESC_Tool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) {
int radiusInfo = brush->GetRadius().X*4+brush->GetRadius().Y*4+7;
void Element_TESC_Tool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) {
int radiusInfo = brush.GetRadius().X*4+brush.GetRadius().Y*4+7;
sim->CreateBox(position1.X, position1.Y, position2.X, position2.Y, toolID | PMAPID(radiusInfo));
}
void Element_TESC_Tool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) {
int radiusInfo = brush->GetRadius().X*4+brush->GetRadius().Y*4+7;
void Element_TESC_Tool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) {
int radiusInfo = brush.GetRadius().X*4+brush.GetRadius().Y*4+7;
sim->FloodParts(position.X, position.Y, toolID | PMAPID(radiusInfo), -1);
}
void PlopTool::Click(Simulation * sim, Brush * brush, ui::Point position)
void PlopTool::Click(Simulation * sim, Brush const &brush, ui::Point position)
{
sim->create_part(-2, position.X, position.Y, TYP(toolID), ID(toolID));
}

View File

@ -31,11 +31,11 @@ public:
VideoBuffer * GetTexture(int width, int height);
void SetTextureGen(VideoBuffer * (*textureGen)(int, int, int));
virtual ~Tool();
virtual void Click(Simulation * sim, Brush * brush, ui::Point position);
virtual void Draw(Simulation * sim, Brush * brush, ui::Point position);
virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false);
virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2);
virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position);
virtual void Click(Simulation * sim, Brush const &brush, ui::Point position);
virtual void Draw(Simulation * sim, Brush const &brush, ui::Point position);
virtual void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false);
virtual void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2);
virtual void DrawFill(Simulation * sim, Brush const &brush, ui::Point position);
};
class GameModel;
@ -51,11 +51,11 @@ public:
}
static VideoBuffer * GetIcon(int toolID, int width, int height);
virtual ~SignTool() {}
void Click(Simulation * sim, Brush * brush, ui::Point position) override;
void Draw(Simulation * sim, Brush * brush, ui::Point position) override { }
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override { }
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { }
void Click(Simulation * sim, Brush const &brush, ui::Point position) override;
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override { }
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { }
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { }
};
class SampleTool: public Tool
@ -69,11 +69,11 @@ public:
}
static VideoBuffer * GetIcon(int toolID, int width, int height);
virtual ~SampleTool() {}
void Click(Simulation * sim, Brush * brush, ui::Point position) override { }
void Draw(Simulation * sim, Brush * brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override { }
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { }
void Click(Simulation * sim, Brush const &brush, ui::Point position) override { }
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { }
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { }
};
class PropertyTool: public Tool
@ -94,11 +94,11 @@ public:
void OpenWindow(Simulation *sim);
virtual ~PropertyTool() {}
virtual void SetProperty(Simulation *sim, ui::Point position);
void Click(Simulation * sim, Brush * brush, ui::Point position) override { }
void Draw(Simulation *sim, Brush *brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override;
void Click(Simulation * sim, Brush const &brush, ui::Point position) override { }
void Draw(Simulation *sim, Brush const &brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override;
};
class GOLTool: public Tool
@ -112,11 +112,11 @@ public:
}
void OpenWindow(Simulation *sim, int toolSelection, int rule = 0, int colour1 = 0, int colour2 = 0);
virtual ~GOLTool() {}
void Click(Simulation * sim, Brush * brush, ui::Point position) override { }
void Draw(Simulation *sim, Brush *brush, ui::Point position) override { };
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override { };
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { };
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { };
void Click(Simulation * sim, Brush const &brush, ui::Point position) override { }
void Draw(Simulation *sim, Brush const &brush, ui::Point position) override { };
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { };
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { };
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { };
};
@ -125,10 +125,10 @@ class ElementTool: public Tool
public:
ElementTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL);
virtual ~ElementTool();
void Draw(Simulation * sim, Brush * brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override;
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override;
};
class Element_LIGH_Tool: public ElementTool
@ -138,10 +138,10 @@ public:
ElementTool(id, name, description, r, g, b, identifier, textureGen)
{ }
virtual ~Element_LIGH_Tool() { }
void Click(Simulation * sim, Brush * brush, ui::Point position) override { }
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { }
void Click(Simulation * sim, Brush const &brush, ui::Point position) override { }
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { }
};
class Element_TESC_Tool: public ElementTool
@ -151,8 +151,8 @@ public:
ElementTool(id, name, description, r, g, b, identifier, textureGen)
{ }
virtual ~Element_TESC_Tool() {}
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override;
};
class PlopTool: public ElementTool
@ -162,11 +162,11 @@ public:
ElementTool(id, name, description, r, g, b, identifier, textureGen)
{ }
virtual ~PlopTool() { }
void Draw(Simulation * sim, Brush * brush, ui::Point position) override { }
void Click(Simulation * sim, Brush * brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override { }
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { }
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override { }
void Click(Simulation * sim, Brush const &brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { }
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { }
};
class WallTool: public Tool
@ -174,10 +174,10 @@ class WallTool: public Tool
public:
WallTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL);
virtual ~WallTool();
void Draw(Simulation * sim, Brush * brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override;
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override;
};
class WindTool: public Tool
@ -185,8 +185,8 @@ class WindTool: public Tool
public:
WindTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL);
virtual ~WindTool() { }
void Draw(Simulation * sim, Brush * brush, ui::Point position) override { }
void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { }
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override { }
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { }
};

View File

@ -11,16 +11,22 @@
class TriangleBrush: public Brush
{
ui::Point radius;
public:
TriangleBrush(ui::Point size_):
Brush(size_)
TriangleBrush(ui::Point radius):
Brush(),
radius(radius)
{
SetRadius(size_);
};
void GenerateBitmap() override
}
virtual ~TriangleBrush() override = default;
std::pair<ui::Point, std::unique_ptr<unsigned char []>> GenerateBitmap() const override
{
delete[] bitmap;
bitmap = new unsigned char[size.X*size.Y];
ui::Point size = radius * 2 + 1;
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
int rx = radius.X;
int ry = radius.Y;
for(int x = -rx; x <= rx; x++)
@ -37,5 +43,17 @@ public:
}
}
}
return std::make_pair(radius, std::move(bitmap));
}
ui::Point GetRadius() const override
{
return radius;
}
void SetRadius(ui::Point radius) override
{
this->radius = radius;
InvalidateCache();
}
};

View File

@ -489,9 +489,9 @@ int LuaScriptInterface::tpt_index(lua_State *l)
else if (byteStringEqualsLiteral(key, "selectedreplace"))
return tpt_lua_pushByteString(l, m->GetActiveTool(3)->GetIdentifier()), 1;
else if (byteStringEqualsLiteral(key, "brushx"))
return lua_pushnumber(l, m->GetBrush()->GetRadius().X), 1;
return lua_pushnumber(l, m->GetBrush().GetRadius().X), 1;
else if (byteStringEqualsLiteral(key, "brushy"))
return lua_pushnumber(l, m->GetBrush()->GetRadius().Y), 1;
return lua_pushnumber(l, m->GetBrush().GetRadius().Y), 1;
else if (byteStringEqualsLiteral(key, "brushID"))
return lua_pushnumber(l, m->GetBrushID()), 1;
else if (byteStringEqualsLiteral(key, "decoSpace"))
@ -542,7 +542,7 @@ int LuaScriptInterface::tpt_newIndex(lua_State *l)
if (brushx < 0 || brushx >= XRES)
luaL_error(l, "Invalid brush width");
c->SetBrushSize(ui::Point(brushx, m->GetBrush()->GetRadius().Y));
c->SetBrushSize(ui::Point(brushx, m->GetBrush().GetRadius().Y));
}
else if (byteStringEqualsLiteral(key, "brushy"))
{
@ -550,7 +550,7 @@ int LuaScriptInterface::tpt_newIndex(lua_State *l)
if (brushy < 0 || brushy >= YRES)
luaL_error(l, "Invalid brush height");
c->SetBrushSize(ui::Point(m->GetBrush()->GetRadius().X, brushy));
c->SetBrushSize(ui::Point(m->GetBrush().GetRadius().X, brushy));
}
else if (byteStringEqualsLiteral(key, "brushID"))
m->SetBrushID(luaL_checkinteger(l, 3));
@ -1472,13 +1472,13 @@ int LuaScriptInterface::simulation_createParts(lua_State * l)
int brush = luaL_optint(l,6,CIRCLE_BRUSH);
int flags = luaL_optint(l,7,luacon_sim->replaceModeFlags);
std::vector<Brush*> brushList = luacon_model->GetBrushList();
auto &brushList = luacon_model->GetBrushList();
if (brush < 0 || brush >= (int)brushList.size())
return luaL_error(l, "Invalid brush id '%d'", brush);
ui::Point tempRadius = brushList[brush]->GetRadius();
brushList[brush]->SetRadius(ui::Point(rx, ry));
int ret = luacon_sim->CreateParts(x, y, c, brushList[brush], flags);
int ret = luacon_sim->CreateParts(x, y, c, *brushList[brush], flags);
brushList[brush]->SetRadius(tempRadius);
lua_pushinteger(l, ret);
return 1;
@ -1496,13 +1496,13 @@ int LuaScriptInterface::simulation_createLine(lua_State * l)
int brush = luaL_optint(l,8,CIRCLE_BRUSH);
int flags = luaL_optint(l,9,luacon_sim->replaceModeFlags);
std::vector<Brush*> brushList = luacon_model->GetBrushList();
auto &brushList = luacon_model->GetBrushList();
if (brush < 0 || brush >= (int)brushList.size())
return luaL_error(l, "Invalid brush id '%d'", brush);
ui::Point tempRadius = brushList[brush]->GetRadius();
brushList[brush]->SetRadius(ui::Point(rx, ry));
luacon_sim->CreateLine(x1, y1, x2, y2, c, brushList[brush], flags);
luacon_sim->CreateLine(x1, y1, x2, y2, c, *brushList[brush], flags);
brushList[brush]->SetRadius(tempRadius);
return 0;
}
@ -1627,13 +1627,13 @@ int LuaScriptInterface::simulation_toolBrush(lua_State * l)
else if (tool < 0 || tool > (int)luacon_sim->tools.size())
return luaL_error(l, "Invalid tool id '%d'", tool);
std::vector<Brush*> brushList = luacon_model->GetBrushList();
auto &brushList = luacon_model->GetBrushList();
if (brush < 0 || brush >= (int)brushList.size())
return luaL_error(l, "Invalid brush id '%d'", brush);
ui::Point tempRadius = brushList[brush]->GetRadius();
brushList[brush]->SetRadius(ui::Point(rx, ry));
int ret = luacon_sim->ToolBrush(x, y, tool, brushList[brush], strength);
int ret = luacon_sim->ToolBrush(x, y, tool, *brushList[brush], strength);
brushList[brush]->SetRadius(tempRadius);
lua_pushinteger(l, ret);
return 1;
@ -1656,7 +1656,7 @@ int LuaScriptInterface::simulation_toolLine(lua_State * l)
if (tool < 0 || tool >= (int)luacon_sim->tools.size()+1)
return luaL_error(l, "Invalid tool id '%d'", tool);
std::vector<Brush*> brushList = luacon_model->GetBrushList();
auto &brushList = luacon_model->GetBrushList();
if (brush < 0 || brush >= (int)brushList.size())
return luaL_error(l, "Invalid brush id '%d'", brush);
ui::Point tempRadius = brushList[brush]->GetRadius();
@ -1667,11 +1667,11 @@ int LuaScriptInterface::simulation_toolLine(lua_State * l)
Tool *windTool = luacon_model->GetToolFromIdentifier("DEFAULT_UI_WIND");
float oldStrength = windTool->GetStrength();
windTool->SetStrength(strength);
windTool->DrawLine(luacon_sim, brushList[brush], ui::Point(x1, y1), ui::Point(x2, y2));
windTool->DrawLine(luacon_sim, *brushList[brush], ui::Point(x1, y1), ui::Point(x2, y2));
windTool->SetStrength(oldStrength);
}
else
luacon_sim->ToolLine(x1, y1, x2, y2, tool, brushList[brush], strength);
luacon_sim->ToolLine(x1, y1, x2, y2, tool, *brushList[brush], strength);
brushList[brush]->SetRadius(tempRadius);
return 0;
}
@ -1711,13 +1711,13 @@ int LuaScriptInterface::simulation_decoBrush(lua_State * l)
int tool = luaL_optint(l,9,DECO_DRAW);
int brush = luaL_optint(l,10,CIRCLE_BRUSH);
std::vector<Brush*> brushList = luacon_model->GetBrushList();
auto &brushList = luacon_model->GetBrushList();
if (brush < 0 || brush >= (int)brushList.size())
return luaL_error(l, "Invalid brush id '%d'", brush);
ui::Point tempRadius = brushList[brush]->GetRadius();
brushList[brush]->SetRadius(ui::Point(rx, ry));
luacon_sim->ApplyDecorationPoint(x, y, r, g, b, a, tool, brushList[brush]);
luacon_sim->ApplyDecorationPoint(x, y, r, g, b, a, tool, *brushList[brush]);
brushList[brush]->SetRadius(tempRadius);
return 0;
}
@ -1740,13 +1740,13 @@ int LuaScriptInterface::simulation_decoLine(lua_State * l)
if (x1 < 0 || x2 < 0 || x1 >= XRES || x2 >= XRES || y1 < 0 || y2 < 0 || y1 >= YRES || y2 >= YRES)
return luaL_error(l, "coordinates out of range (%d,%d),(%d,%d)", x1, y1, x2, y2);
std::vector<Brush*> brushList = luacon_model->GetBrushList();
auto &brushList = luacon_model->GetBrushList();
if (brush < 0 || brush >= (int)brushList.size())
return luaL_error(l, "Invalid brush id '%d'", brush);
ui::Point tempRadius = brushList[brush]->GetRadius();
brushList[brush]->SetRadius(ui::Point(rx, ry));
luacon_sim->ApplyDecorationLine(x1, y1, x2, y2, r, g, b, a, tool, brushList[brush]);
luacon_sim->ApplyDecorationLine(x1, y1, x2, y2, r, g, b, a, tool, *brushList[brush]);
brushList[brush]->SetRadius(tempRadius);
return 0;
}
@ -2166,47 +2166,18 @@ int BrushClosure(lua_State * l)
// see Simulation::ToolBrush
int positionX = lua_tointeger(l, lua_upvalueindex(1));
int positionY = lua_tointeger(l, lua_upvalueindex(2));
int radiusX = lua_tointeger(l, lua_upvalueindex(3));
int radiusY = lua_tointeger(l, lua_upvalueindex(4));
int sizeX = lua_tointeger(l, lua_upvalueindex(5));
int sizeY = lua_tointeger(l, lua_upvalueindex(6));
int x = lua_tointeger(l, lua_upvalueindex(7));
int y = lua_tointeger(l, lua_upvalueindex(8));
unsigned char *bitmap = (unsigned char *)lua_touserdata(l, lua_upvalueindex(9));
int i = lua_tointeger(l, lua_upvalueindex(3));
int size = lua_tointeger(l, lua_upvalueindex(4));
auto points = reinterpret_cast<ui::Point *>(lua_touserdata(l, lua_upvalueindex(5)));
int yield_x, yield_y;
while (true)
{
if (!(y < sizeY))
if (i == size)
return 0;
if (x < sizeX)
{
bool yield_coords = false;
if (bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
{
yield_coords = true;
yield_x = positionX+(x-radiusX);
yield_y = positionY+(y-radiusY);
}
x++;
if (yield_coords)
break;
}
else
{
x = 0;
y++;
}
}
lua_pushnumber(l, x);
lua_replace(l, lua_upvalueindex(7));
lua_pushnumber(l, y);
lua_replace(l, lua_upvalueindex(8));
lua_pushnumber(l, i + 1);
lua_replace(l, lua_upvalueindex(3));
lua_pushnumber(l, yield_x);
lua_pushnumber(l, yield_y);
lua_pushnumber(l, points[i].X + positionX);
lua_pushnumber(l, points[i].Y + positionY);
return 2;
}
@ -2216,43 +2187,37 @@ int LuaScriptInterface::simulation_brush(lua_State * l)
int positionX = luaL_checkint(l, 1);
int positionY = luaL_checkint(l, 2);
int brushradiusX, brushradiusY;
if (argCount >= 4 || !luacon_model->GetBrush())
if (argCount >= 4)
{
brushradiusX = luaL_checkint(l, 3);
brushradiusY = luaL_checkint(l, 4);
}
else
{
ui::Point radius = luacon_model->GetBrush()->GetRadius();
ui::Point radius = luacon_model->GetBrush().GetRadius();
brushradiusX = radius.X;
brushradiusY = radius.Y;
}
int brushID = luaL_optint(l, 5, luacon_model->GetBrushID());
std::vector<Brush *> brushList = luacon_model->GetBrushList();
auto &brushList = luacon_model->GetBrushList();
if (brushID < 0 || brushID >= (int)brushList.size())
return luaL_error(l, "Invalid brush id '%d'", brushID);
ui::Point tempRadius = brushList[brushID]->GetRadius();
brushList[brushID]->SetRadius(ui::Point(brushradiusX, brushradiusY));
Brush &brush = *brushList[brushID];
ui::Point tempRadius = brush.GetRadius();
brush.SetRadius(ui::Point(brushradiusX, brushradiusY));
lua_pushnumber(l, positionX);
lua_pushnumber(l, positionY);
int radiusX = brushList[brushID]->GetRadius().X;
int radiusY = brushList[brushID]->GetRadius().Y;
int sizeX = brushList[brushID]->GetSize().X;
int sizeY = brushList[brushID]->GetSize().Y;
lua_pushnumber(l, radiusX);
lua_pushnumber(l, radiusY);
lua_pushnumber(l, sizeX);
lua_pushnumber(l, sizeY);
lua_pushnumber(l, 0);
lua_pushnumber(l, 0);
int bitmapSize = sizeX * sizeY * sizeof(unsigned char);
void *bitmapCopy = lua_newuserdata(l, bitmapSize);
memcpy(bitmapCopy, brushList[brushID]->GetBitmap(), bitmapSize);
brushList[brushID]->SetRadius(tempRadius);
std::vector<ui::Point> points;
std::copy(brush.begin(), brush.end(), std::back_inserter(points));
lua_pushnumber(l, 0); // index
lua_pushnumber(l, points.size());
auto points_ud = reinterpret_cast<ui::Point *>(lua_newuserdata(l, points.size() * sizeof(ui::Point)));
std::copy(points.begin(), points.end(), points_ud);
brush.SetRadius(tempRadius);
lua_pushcclosure(l, BrushClosure, 9);
lua_pushcclosure(l, BrushClosure, 5);
return 1;
}

View File

@ -179,7 +179,7 @@ int Simulation::Tool(int x, int y, int tool, int brushX, int brushY, float stren
return tools[tool].Perform(this, cpart, x, y, brushX, brushY, strength);
}
int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush * cBrush)
int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush const *cBrush)
{
if(cBrush)
{
@ -239,7 +239,7 @@ int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush * cBru
return 1;
}
void Simulation::CreateWallLine(int x1, int y1, int x2, int y2, int rx, int ry, int wall, Brush * cBrush)
void Simulation::CreateWallLine(int x1, int y1, int x2, int y2, int rx, int ry, int wall, Brush const *cBrush)
{
int x, y, dx, dy, sy;
bool reverseXY = abs(y2-y1) > abs(x2-x1);
@ -608,37 +608,24 @@ void Simulation::ApplyDecoration(int x, int y, int colR_, int colG_, int colB_,
parts[ID(rp)].dcolour = ((colA_<<24)|(colR_<<16)|(colG_<<8)|colB_);
}
void Simulation::ApplyDecorationPoint(int positionX, int positionY, int colR, int colG, int colB, int colA, int mode, Brush * cBrush)
void Simulation::ApplyDecorationPoint(int positionX, int positionY, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush)
{
if(cBrush)
for (ui::Point off : cBrush)
{
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
unsigned char *bitmap = cBrush->GetBitmap();
for(int y = 0; y < sizeY; y++)
{
for(int x = 0; x < sizeX; x++)
{
if(bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
{
ApplyDecoration(positionX+(x-radiusX), positionY+(y-radiusY), colR, colG, colB, colA, mode);
}
}
}
ui::Point coords = ui::Point(positionX, positionY) + off;
if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES)
ApplyDecoration(coords.X, coords.Y, colR, colG, colB, colA, mode);
}
}
void Simulation::ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush * cBrush)
void Simulation::ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush)
{
bool reverseXY = abs(y2-y1) > abs(x2-x1);
int x, y, dx, dy, sy, rx = 0, ry = 0;
float e = 0.0f, de;
if(cBrush)
{
rx = cBrush->GetRadius().X;
ry = cBrush->GetRadius().Y;
}
rx = cBrush.GetRadius().X;
ry = cBrush.GetRadius().Y;
if (reverseXY)
{
@ -784,24 +771,21 @@ void Simulation::ApplyDecorationFill(Renderer *ren, int x, int y, int colR, int
free(bitmap);
}
int Simulation::ToolBrush(int positionX, int positionY, int tool, Brush * cBrush, float strength)
int Simulation::ToolBrush(int positionX, int positionY, int tool, Brush const &cBrush, float strength)
{
if(cBrush)
for (ui::Point off : cBrush)
{
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
unsigned char *bitmap = cBrush->GetBitmap();
for(int y = 0; y < sizeY; y++)
for(int x = 0; x < sizeX; x++)
if(bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
Tool(positionX + (x - radiusX), positionY + (y - radiusY), tool, positionX, positionY, strength);
ui::Point coords = ui::Point(positionX, positionY) + off;
if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES)
Tool(coords.X, coords.Y, tool, positionX, positionY, strength);
}
return 0;
}
void Simulation::ToolLine(int x1, int y1, int x2, int y2, int tool, Brush * cBrush, float strength)
void Simulation::ToolLine(int x1, int y1, int x2, int y2, int tool, Brush const &cBrush, float strength)
{
bool reverseXY = abs(y2-y1) > abs(x2-x1);
int x, y, dx, dy, sy, rx = cBrush->GetRadius().X, ry = cBrush->GetRadius().Y;
int x, y, dx, dy, sy, rx = cBrush.GetRadius().X, ry = cBrush.GetRadius().Y;
float e = 0.0f, de;
if (reverseXY)
{
@ -871,14 +855,11 @@ void Simulation::ToolBox(int x1, int y1, int x2, int y2, int tool, float strengt
Tool(i, j, tool, brushX, brushY, strength);
}
int Simulation::CreateParts(int positionX, int positionY, int c, Brush * cBrush, int flags)
int Simulation::CreateParts(int positionX, int positionY, int c, Brush const &cBrush, int flags)
{
if (flags == -1)
flags = replaceModeFlags;
if (cBrush)
{
int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y;
unsigned char *bitmap = cBrush->GetBitmap();
int radiusX = cBrush.GetRadius().X, radiusY = cBrush.GetRadius().Y;
// special case for LIGH
if (c == PT_LIGH)
@ -900,16 +881,11 @@ int Simulation::CreateParts(int positionX, int positionY, int c, Brush * cBrush,
c = PMAP(newtmp, c);
}
for (int y = sizeY-1; y >=0; y--)
for (ui::Point off : cBrush)
{
for (int x = 0; x < sizeX; x++)
{
if (bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES))
{
CreatePartFlags(positionX+(x-radiusX), positionY+(y-radiusY), c, flags);
}
}
}
ui::Point coords = ui::Point(positionX, positionY) + off;
if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES)
CreatePartFlags(coords.X, coords.Y, c, flags);
}
return 0;
}
@ -948,9 +924,9 @@ int Simulation::CreateParts(int x, int y, int rx, int ry, int c, int flags)
return !created;
}
void Simulation::CreateLine(int x1, int y1, int x2, int y2, int c, Brush * cBrush, int flags)
void Simulation::CreateLine(int x1, int y1, int x2, int y2, int c, Brush const &cBrush, int flags)
{
int x, y, dx, dy, sy, rx = cBrush->GetRadius().X, ry = cBrush->GetRadius().Y;
int x, y, dx, dy, sy, rx = cBrush.GetRadius().X, ry = cBrush.GetRadius().Y;
bool reverseXY = abs(y2-y1) > abs(x2-x1);
float e = 0.0f, de;
if (reverseXY)

View File

@ -15,6 +15,7 @@
#include <vector>
#include <array>
#include <memory>
#include <optional>
constexpr int CHANNELS = int(MAX_TEMP - 73) / 100 + 2;
@ -174,29 +175,29 @@ public:
//Drawing Deco
void ApplyDecoration(int x, int y, int colR, int colG, int colB, int colA, int mode);
void ApplyDecorationPoint(int x, int y, int colR, int colG, int colB, int colA, int mode, Brush * cBrush = NULL);
void ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush * cBrush = NULL);
void ApplyDecorationPoint(int x, int y, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush);
void ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush);
void ApplyDecorationBox(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode);
bool ColorCompare(Renderer *ren, int x, int y, int replaceR, int replaceG, int replaceB);
void ApplyDecorationFill(Renderer *ren, int x, int y, int colR, int colG, int colB, int colA, int replaceR, int replaceG, int replaceB);
//Drawing Tools like HEAT, AIR, and GRAV
int Tool(int x, int y, int tool, int brushX, int brushY, float strength = 1.0f);
int ToolBrush(int x, int y, int tool, Brush * cBrush, float strength = 1.0f);
void ToolLine(int x1, int y1, int x2, int y2, int tool, Brush * cBrush, float strength = 1.0f);
int ToolBrush(int x, int y, int tool, Brush const &cBrush, float strength = 1.0f);
void ToolLine(int x1, int y1, int x2, int y2, int tool, Brush const &cBrush, float strength = 1.0f);
void ToolBox(int x1, int y1, int x2, int y2, int tool, float strength = 1.0f);
//Drawing Walls
int CreateWalls(int x, int y, int rx, int ry, int wall, Brush * cBrush = NULL);
void CreateWallLine(int x1, int y1, int x2, int y2, int rx, int ry, int wall, Brush * cBrush = NULL);
int CreateWalls(int x, int y, int rx, int ry, int wall, Brush const *cBrush = nullptr);
void CreateWallLine(int x1, int y1, int x2, int y2, int rx, int ry, int wall, Brush const *cBrush = nullptr);
void CreateWallBox(int x1, int y1, int x2, int y2, int wall);
int FloodWalls(int x, int y, int wall, int bm);
//Drawing Particles
int CreateParts(int positionX, int positionY, int c, Brush * cBrush, int flags = -1);
int CreateParts(int positionX, int positionY, int c, Brush const &cBrush, int flags = -1);
int CreateParts(int x, int y, int rx, int ry, int c, int flags = -1);
int CreatePartFlags(int x, int y, int c, int flags);
void CreateLine(int x1, int y1, int x2, int y2, int c, Brush * cBrush, int flags = -1);
void CreateLine(int x1, int y1, int x2, int y2, int c, Brush const &cBrush, int flags = -1);
void CreateLine(int x1, int y1, int x2, int y2, int c);
void CreateBox(int x1, int y1, int x2, int y2, int c, int flags = -1);
int FloodParts(int x, int y, int c, int cm, int flags = -1);