321 lines
9.8 KiB
C
321 lines
9.8 KiB
C
char strFPS[20];
|
|
char strDyeDiff[20];
|
|
char strVelDiff[20];
|
|
char strDyeForce[20];
|
|
char strVelForce[20];
|
|
char strRadius[20];
|
|
char strPressureIter[20];
|
|
char strEmptyTreshold[20];
|
|
char strSaturateTreshold[20];
|
|
|
|
// Main Screen
|
|
void main_menu() {
|
|
const int gap = 8;
|
|
const int startY = 11;
|
|
dhline(5, C_BLACK);
|
|
dtext_opt(64, 2, C_BLACK, C_WHITE, DTEXT_CENTER, DTEXT_TOP, " CASIO FLUID SIMULATION ", -1);
|
|
dtext_opt(3, startY, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "Implementation of Jos Stam's", -1);
|
|
dtext_opt(3, startY + gap, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "\"Real Time Fluid Dynamics for", -1);
|
|
dtext_opt(3, startY + gap*2, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "games\" paper on monochrome", -1);
|
|
dtext_opt(3, startY + gap*3, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "Casio calculators", -1);
|
|
dtext_opt(3, startY + gap*4+2, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[Optn] key displays the help", -1);
|
|
dtext_opt(124, 62, C_BLACK, C_WHITE, DTEXT_RIGHT, DTEXT_BOTTOM, "[EXE] Start", -1);
|
|
dupdate();
|
|
dclear(C_WHITE);
|
|
|
|
sleep_ms(500);
|
|
|
|
while(1) {
|
|
clearevents();
|
|
uint key = getkey().key;
|
|
if (key == KEY_EXE || key == K_HELP) break;
|
|
}
|
|
}
|
|
|
|
// Controls/Help Menu
|
|
int help_menu() {
|
|
const int margin = 2;
|
|
|
|
drect_border(margin, margin, 128 - margin-1, 64 - margin-1, C_WHITE, 1, C_BLACK);
|
|
dtext_opt(margin+2, margin+3+8*0, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[Arrows]: Interact", -1);
|
|
dtext_opt(margin+2, margin+3+8*1, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[Shift]: Toggle edit mode", -1);
|
|
dtext_opt(margin+2, margin+3+8*2, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[Alpha]: Toggle color mode", -1);
|
|
dtext_opt(margin+2, margin+3+8*3, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[Del]: Reset the simulation", -1);
|
|
dtext_opt(margin+2, margin+3+8*4, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[+]/[-]: Toggle fullscreen", -1);
|
|
dtext_opt(margin+2, margin+3+8*5, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[x]: Hide/Show FPS", -1);
|
|
dtext_opt(margin+2, margin+3+8*6, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[Exit]: Quit [EXE]: Continue", -1);
|
|
dupdate();
|
|
dclear(C_WHITE);
|
|
|
|
while(1) {
|
|
uint key = getkey().key;
|
|
if (key == KEY_EXIT) return -1;
|
|
if (key == KEY_EXE || key == K_HELP) return 0;
|
|
}
|
|
// if (getkey().key == KEY_EXIT) return -1;
|
|
// return 0;
|
|
}
|
|
|
|
// Fluid Simulation Settings Menu
|
|
void settings_menu(bool redraw) {
|
|
static int selected = 0;
|
|
const int menuX = 66;
|
|
const int menuY = 2;
|
|
const int gap = 8;
|
|
const int rx = 64;
|
|
const bool activated = redraw;
|
|
bool updateRect = false, updateDyeD = activated, updateVelD = activated, updateDyeF = activated, updateVelF = activated, updateRadius = activated, updatePressureIter = activated;
|
|
static bool releaseParams = true;
|
|
|
|
if (currentView == 1 && releaseParams && keydown(K_PARAMS)) {
|
|
releaseParams = false;
|
|
currentView = 0;
|
|
int ry = menuY+gap*(selected+1)+2;
|
|
drect(rx, ry, rx, ry+2, C_WHITE);
|
|
drect_border(63, 0, 127, H-1, C_NONE, 1, C_WHITE);
|
|
}
|
|
else if (currentView != 1 && releaseParams && keydown(K_PARAMS)) {
|
|
releaseParams = false;
|
|
currentView = 1;
|
|
updateRect = true;
|
|
updateDyeD = true, updateVelD = true, updateDyeF = true, updateVelF = true, updateRadius = true, updatePressureIter = true;
|
|
drect(64, 0, 128, 64, C_WHITE);
|
|
drect_border(0, 0, W-1, H-1, C_NONE, 1, C_WHITE);
|
|
} else if (!keydown(K_PARAMS)) {
|
|
releaseParams = true;
|
|
}
|
|
|
|
if (currentView == 0) {
|
|
drect_border(0, 0, W-1, H-1, C_NONE, 1, C_BLACK);
|
|
if (!redraw) return;
|
|
} else if (currentView == 2) return;
|
|
{
|
|
drect_border(0, 0, W-1, H-1, C_NONE, 1, C_WHITE);
|
|
drect_border(63, 0, 127, H-1, C_NONE, 1, C_BLACK);
|
|
}
|
|
|
|
if (keydown(KEY_LEFT)) {
|
|
if (selected == 0 && dyeDiffusion > 0) {
|
|
dyeDiffusion -= PREC_STEP;
|
|
updateDyeD = true;
|
|
}
|
|
else if (selected == 1 && velDiffusion > 0) {
|
|
velDiffusion -= PREC_STEP;
|
|
updateVelD = true;
|
|
}
|
|
else if (selected == 2 && dyeIntensity > 0) {
|
|
dyeIntensity -= PREC_STEP;
|
|
updateDyeF = true;
|
|
}
|
|
else if (selected == 3 && velIntensity > 0) {
|
|
velIntensity -= PREC_STEP;
|
|
updateVelF = true;
|
|
}
|
|
else if (selected == 4 && radius > ONE) {
|
|
radius -= FIX(1);
|
|
updateRadius = true;
|
|
}
|
|
else if (selected == 5 && pressureIterations > 0) {
|
|
pressureIterations--;
|
|
updatePressureIter = true;
|
|
}
|
|
}
|
|
else if (keydown(KEY_RIGHT)) {
|
|
if (selected == 0 && dyeDiffusion < ONE) {
|
|
dyeDiffusion += PREC_STEP;
|
|
updateDyeD = true;
|
|
}
|
|
else if (selected == 1 && velDiffusion < ONE) {
|
|
velDiffusion += PREC_STEP;
|
|
updateVelD = true;
|
|
}
|
|
else if (selected == 2 && dyeIntensity < ONE*2) {
|
|
dyeIntensity += PREC_STEP;
|
|
updateDyeF = true;
|
|
}
|
|
else if (selected == 3 && velIntensity < ONE*2) {
|
|
velIntensity += PREC_STEP;
|
|
updateVelF = true;
|
|
}
|
|
else if (selected == 4 && radius < ONE*10) {
|
|
radius += FIX(1);
|
|
updateRadius = true;
|
|
}
|
|
else if (selected == 5) {
|
|
pressureIterations++;
|
|
updatePressureIter = true;
|
|
}
|
|
}
|
|
else if (keydown(KEY_UP)) {
|
|
int ry = menuY+gap*(selected+1)+2;
|
|
drect(rx, ry, rx, ry+2, C_WHITE);
|
|
if (--selected < 0) selected = 5;
|
|
updateRect = true;
|
|
}
|
|
else if (keydown(KEY_DOWN)) {
|
|
int ry = menuY+gap*(selected+1)+2;
|
|
drect(rx, ry, rx, ry+2, C_WHITE);
|
|
if (++selected > 5) selected = 0;
|
|
updateRect = true;
|
|
}
|
|
|
|
if (updateDyeD) {
|
|
sprintf(strDyeDiff, "dye diff:%.3f ", fixtof(dyeDiffusion));
|
|
dtext_opt(menuX, menuY + gap, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, strDyeDiff, -1);
|
|
}
|
|
if (updateVelD) {
|
|
sprintf(strVelDiff, "vel diff:%.3f ", fixtof(velDiffusion));
|
|
dtext_opt(menuX, menuY + gap*2, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, strVelDiff, -1);
|
|
}
|
|
if (updateDyeF) {
|
|
sprintf(strDyeForce, "dye force:%.1f ", fixtof(dyeIntensity));
|
|
dtext_opt(menuX, menuY + gap*3, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, strDyeForce, -1);
|
|
}
|
|
if (updateVelF) {
|
|
sprintf(strVelForce, "vel force:%.1f ", fixtof(velIntensity));
|
|
dtext_opt(menuX, menuY + gap*4, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, strVelForce, -1);
|
|
}
|
|
if (updateRadius) {
|
|
sprintf(strRadius, "radius: %d ", UNFIX(radius));
|
|
dtext_opt(menuX, menuY + gap*5, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, strRadius, -1);
|
|
}
|
|
if (updatePressureIter) {
|
|
sprintf(strPressureIter, "iterations: %d ", pressureIterations);
|
|
dtext_opt(menuX, menuY + gap*6, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, strPressureIter, -1);
|
|
}
|
|
if (updateRect) {
|
|
int ry = menuY+gap*(selected+1)+2;
|
|
drect(rx, ry, rx, ry+2, C_BLACK);
|
|
}
|
|
}
|
|
|
|
// Fluid color settings Menu
|
|
void color_menu() {
|
|
const int xmargin = 3;
|
|
const float fw = 64. - (float)xmargin * 2.;
|
|
const int y = 22;
|
|
const int h = 5;
|
|
const int bar_overflow = 3;
|
|
const int STEP_MULT = 20;
|
|
|
|
const float tresh1 = fixtof(emptyTreshold);
|
|
const float tresh2 = fixtof(saturateTreshold);
|
|
const int x1 = 64 + xmargin + (int)(tresh1 * fw);
|
|
const int x2 = 64 + xmargin + (int)(tresh2 * fw);
|
|
|
|
static bool x1Selected = true;
|
|
static bool releaseKey = true;
|
|
bool updated = false;
|
|
|
|
// Manage keys
|
|
if (keydown(K_COLORS) && releaseKey) {
|
|
releaseKey = false;
|
|
if (currentView == 2) {
|
|
currentView = 0;
|
|
drect_border(63, 0, 127, H-1, C_NONE, 1, C_WHITE);
|
|
}
|
|
else {
|
|
currentView = 2;
|
|
updated = true;
|
|
}
|
|
} else if (!keydown(K_COLORS) && !releaseKey) {
|
|
releaseKey = true;
|
|
}
|
|
|
|
if (currentView != 2) return;
|
|
|
|
if (keydown(KEY_F1)) {
|
|
emptyTreshold -= PREC_STEP * STEP_MULT;
|
|
if (emptyTreshold < 0) emptyTreshold = 0;
|
|
|
|
x1Selected = true;
|
|
updated = true;
|
|
}
|
|
else if (keydown(KEY_F2)) {
|
|
emptyTreshold += PREC_STEP * STEP_MULT;
|
|
if (emptyTreshold > ONE) emptyTreshold = ONE;
|
|
if (emptyTreshold > saturateTreshold) saturateTreshold = emptyTreshold;
|
|
|
|
x1Selected = true;
|
|
updated = true;
|
|
}
|
|
else if (keydown(KEY_F3)) {
|
|
saturateTreshold -= PREC_STEP * STEP_MULT;
|
|
if (saturateTreshold < 0) saturateTreshold = 0;
|
|
if (saturateTreshold < emptyTreshold) emptyTreshold = saturateTreshold;
|
|
|
|
x1Selected = false;
|
|
updated = true;
|
|
}
|
|
else if (keydown(KEY_F4)) {
|
|
saturateTreshold += PREC_STEP * STEP_MULT;
|
|
if (saturateTreshold > ONE) saturateTreshold = ONE;
|
|
|
|
x1Selected = false;
|
|
updated = true;
|
|
}
|
|
else if (keydown(KEY_F5)) {
|
|
fix diff = saturateTreshold - emptyTreshold;
|
|
|
|
emptyTreshold -= PREC_STEP * STEP_MULT;
|
|
if (emptyTreshold < 0) emptyTreshold = 0;
|
|
saturateTreshold = emptyTreshold + diff;
|
|
|
|
x1Selected = true;
|
|
updated = true;
|
|
}
|
|
else if (keydown(KEY_F6)) {
|
|
fix diff = saturateTreshold - emptyTreshold;
|
|
|
|
saturateTreshold += PREC_STEP * STEP_MULT;
|
|
if (saturateTreshold > ONE) saturateTreshold = ONE;
|
|
emptyTreshold = saturateTreshold - diff;
|
|
|
|
x1Selected = false;
|
|
updated = true;
|
|
}
|
|
|
|
if (updated) {
|
|
// Clear
|
|
drect(64, 0, 128, 64, C_WHITE);
|
|
drect_border(0, 0, W-1, H-1, C_NONE, 1, C_WHITE);
|
|
|
|
// Draw selectors
|
|
if (x1Selected) {
|
|
drect(x1-1, y - bar_overflow-1, x1+1, y+h+bar_overflow+1, C_BLACK);
|
|
dline(x2, y - bar_overflow, x2, y+h+bar_overflow, C_BLACK);
|
|
} else {
|
|
dline(x1, y - bar_overflow, x1, y+h+bar_overflow, C_BLACK);
|
|
drect(x2-1, y - bar_overflow-1, x2+1, y+h+bar_overflow+1, C_BLACK);
|
|
}
|
|
|
|
// Draw white band
|
|
drect(64 + xmargin, y, x1, y + h, C_WHITE);
|
|
|
|
// Draw checker band
|
|
for (int j = y; j <= y+h; j++) {
|
|
dline(x1, j, x2, j, j%2 ? C_BLACK : C_WHITE);
|
|
}
|
|
for (int i = x1; i < x2; i+=2) {
|
|
dline(i, y, i, y+h, C_BLACK);
|
|
}
|
|
|
|
// Draw black band
|
|
drect(x2, y, 128 - xmargin, y + h, C_BLACK);
|
|
|
|
// Draw border
|
|
drect_border(64 + xmargin-1, y-1, 128 - xmargin+1, y+h+1, C_NONE, 1, C_BLACK);
|
|
|
|
// Draw float values
|
|
sprintf(strEmptyTreshold, "%.2f", tresh1);
|
|
sprintf(strSaturateTreshold, "%.2f", tresh2);
|
|
dtext_opt(x1, y - bar_overflow - 1, C_BLACK, C_WHITE, DTEXT_CENTER, DTEXT_BOTTOM, strEmptyTreshold, -1);
|
|
dtext_opt(x2, y + h + bar_overflow + 1, C_BLACK, C_WHITE, DTEXT_CENTER, DTEXT_TOP, strSaturateTreshold, -1);
|
|
|
|
dtext_opt(65, 40, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[F1/F2] Lower", -1);
|
|
dtext_opt(65, 48, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[F3/F4] Upper", -1);
|
|
dtext_opt(65, 56, C_BLACK, C_WHITE, DTEXT_LEFT, DTEXT_TOP, "[F5/F6] Both", -1);
|
|
}
|
|
|
|
drect_border(63, 0, 127, H-1, C_NONE, 1, C_BLACK);
|
|
} |