diff --git a/CMakeLists.txt b/CMakeLists.txt index 458af89..379033a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # toolchain file and module path of the fxSDK cmake_minimum_required(VERSION 3.15) -project(MyAddin) +project(Duet) include(GenerateG1A) include(GenerateG3A) @@ -11,31 +11,19 @@ find_package(Gint 2.1 REQUIRED) set(SOURCES src/main.c + src/render.c # ... ) -# Shared assets, fx-9860G-only assets and fx-CG-50-only assets set(ASSETS - # ... -) -set(ASSETS_fx - assets-fx/example.png - # ... -) -set(ASSETS_cg assets-cg/example.png # ... ) -fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} WITH_METADATA) +fxconv_declare_assets(${ASSETS} WITH_METADATA) -add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}}) -target_compile_options(myaddin PRIVATE -Wall -Wextra -Os) -target_link_libraries(myaddin Gint::Gint) +add_executable(addin ${SOURCES} ${ASSETS}) +target_compile_options(addin PRIVATE -Wall -Wextra -Os) +target_link_libraries(addin Gint::Gint) -if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) - generate_g1a(TARGET myaddin OUTPUT "MyAddin.g1a" - NAME "MyAddin" ICON assets-fx/icon.png) -elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) - generate_g3a(TARGET myaddin OUTPUT "MyAddin.g3a" - NAME "MyAddin" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png) -endif() +generate_g3a(TARGET addin OUTPUT "Duet.g3a" + NAME "Duet" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png) diff --git a/src/duet.h b/src/duet.h index b553bb9..54f9724 100644 --- a/src/duet.h +++ b/src/duet.h @@ -1,9 +1,12 @@ #pragma once -#include #include - #include +#include + +#include + +#define __BSD_VISIBLE 1 #include //--- @@ -14,6 +17,7 @@ typedef struct { float w, h; /* px */ float x, y; /* px */ float vx, vy; /* px/s */ + float r; /* rad */ float vr; /* rad/s */ } rect_t; @@ -57,4 +61,8 @@ typedef struct { // Rendering //--- -void dcircle(int x, int y, int color); +void dcircle(int x, int y, int r, int color, bool fill); + +void dtriangle(int x1, int y1, int x2, int y2, int x3, int y3, int color); + +void drectoid(rect_t const *r, int color); diff --git a/src/main.c b/src/main.c index 556003d..50e1dbe 100644 --- a/src/main.c +++ b/src/main.c @@ -1,15 +1,26 @@ #include #include +#include "duet.h" //rectmeta_t level1[] = { // {.time = 0, .shape = Shape_LongBar, .position = Position_Left} //}; - int main(void) { dclear(C_WHITE); - dtext(1, 1, C_BLACK, "Sample fxSDK add-in."); + + rect_t r = { + .w = 80, + .h = 20, + .x = 200, + .y = 150, + .r = M_PI / 12, + }; + + dcircle(100, 100, 20, C_RED, true); + dtriangle(0, 0, 8, 20, 20, 0, C_BLACK); + drectoid(&r, C_RED); dupdate(); getkey(); diff --git a/src/render.c b/src/render.c index 7cedec0..a0a8e6a 100644 --- a/src/render.c +++ b/src/render.c @@ -1,3 +1,110 @@ -void dcircle(int x, int y, int color) +#include "duet.h" +#include + +/* Bresenham algorithm */ +void dcircle(int cx, int cy, int r0, int color, bool fill) { + int x=-r0, y=0, e=2-2*r0, r=r0; + + do { + dpixel(cx-x, cy-y, color); + dpixel(cx+y, cy-x, color); + dpixel(cx+x, cy+y, color); + dpixel(cx-y, cy+x, color); + + if(fill) { + dline(cx+x, cy-y, cx-x, cy-y, color); + dline(cx+x, cy+y, cx-x, cy+y, color); + } + + r = e; + if(r <= y) + e += (++y * 2) + 1; + if(r > x || e > y) + e += (++x * 2) + 1; + } + while(x < 0); +} + +/* From Windmill::render_triangle_black */ +static int edge_start(int x1, int y1, int x2, int y2, int px, int py) +{ + return (y2 - y1) * (px - x1) - (x2 - x1) * (py - y1); +} +static int min(int x, int y) +{ + return (x < y) ? x : y; +} +static int max(int x, int y) +{ + return (x > y) ? x : y; +} +void dtriangle(int x1, int y1, int x2, int y2, int x3, int y3, int color) +{ + if(y2 > y3) { + int tx=x2, ty=y2; + x2=x3, y2=y3; + x3=tx, y3=ty; + } + if(y1 > y2) { + int tx=x1, ty=y1; + x1=x2, y1=y2; + x2=tx, y2=ty; + } + + // calcul du rectangle circonscrit au triangle + int min_x = max(0, min(x1, min(x2, x3))); + int max_x = min(DWIDTH-1, max(x1, max(x2, x3))); + int min_y = max(0, min(y1, min(y2, y3))); + int max_y = min(DHEIGHT-1, max(y1, max(y2, y3))); + + // calcul des produits vectoriels + int u0_start = edge_start(x2, y2, x3, y3, min_x, min_y); + int u0_step_x = y3 - y2; + int u0_step_y = x2 - x3; + int u1_start = edge_start(x3, y3, x1, y1, min_x, min_y); + int u1_step_x = y1 - y3; + int u1_step_y = x3 - x1; + int u2_start = edge_start(x1, y1, x2, y2, min_x, min_y); + int u2_step_x = y2 - y1; + int u2_step_y = x1 - x2; + + int u0, u1, u2; + + // parcours en ligne + for(int x=min_x; x<=max_x; x++) + { + u0 = u0_start; u1 = u1_start; u2 = u2_start; + + // parcours en colonne + for(int y=min_y; y<=max_y; y++) + { + // si le pixel (x;y) est dans le triangle + if ((u0 | u1 | u2) > 0) + { + dpixel(x, y, color); + } + u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y; + } + u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x; + } +} + +void drectoid(rect_t const *r, int color) +{ + float sin, cos; + sincosf(r->r, &sin, &cos); + + float x0[4] = { r->w/2, -r->w/2, -r->w/2, r->w/2 }; + float y0[4] = { -r->h/2, -r->h/2, r->h/2, r->h/2 }; + + int x[4], y[4]; + + for(int i = 0; i < 4; i++) { + x[i] = r->x + x0[i] * cos + y0[i] * sin; + y[i] = r->y - x0[i] * sin + y0[i] * cos; + } + + dtriangle(x[0], y[0], x[1], y[1], x[2], y[2], color); + dtriangle(x[2], y[2], x[3], y[3], x[0], y[0], color); }