1
0

Extract graphic class

This commit is contained in:
otya128
2016-12-03 13:35:13 +09:00
parent 8d62088854
commit fbd7471b0e
5 changed files with 475 additions and 562 deletions

View File

@@ -299,58 +299,58 @@ class BuiltinFunction
static void GCLS(PetitComputer p, DefaultValue!(int, false) color) static void GCLS(PetitComputer p, DefaultValue!(int, false) color)
{ {
color.setDefaultValue(0); color.setDefaultValue(0);
p.gfill(p.useGRP, 0, 0, 511, 511, cast(int)color); p.graphic.gfill(p.graphic.useGRP, 0, 0, 511, 511, cast(int)color);
} }
static void GPSET(PetitComputer p, int x, int y, DefaultValue!(int, false) color) static void GPSET(PetitComputer p, int x, int y, DefaultValue!(int, false) color)
{ {
color.setDefaultValue(p.gcolor); color.setDefaultValue(p.graphic.gcolor);
p.gpset(p.useGRP, x, y, cast(int)color); p.graphic.gpset(p.graphic.useGRP, x, y, cast(int)color);
} }
static void GLINE(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color) static void GLINE(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color)
{ {
color.setDefaultValue(p.gcolor); color.setDefaultValue(p.graphic.gcolor);
p.gline(p.useGRP, x, y, x2, y2, cast(int)color); p.graphic.gline(p.graphic.useGRP, x, y, x2, y2, cast(int)color);
} }
static void GBOX(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color) static void GBOX(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color)
{ {
color.setDefaultValue(p.gcolor); color.setDefaultValue(p.graphic.gcolor);
p.gbox(p.useGRP, x, y, x2, y2, cast(int)color); p.graphic.gbox(p.graphic.useGRP, x, y, x2, y2, cast(int)color);
} }
static void GFILL(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color) static void GFILL(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color)
{ {
color.setDefaultValue(p.gcolor); color.setDefaultValue(p.graphic.gcolor);
p.gfill(p.useGRP, x, y, x2, y2, cast(int)color); p.graphic.gfill(p.graphic.useGRP, x, y, x2, y2, cast(int)color);
} }
//X,Y,R[,COLOR] //X,Y,R[,COLOR]
//X,Y,R,SR,ER[,COLOR] //X,Y,R,SR,ER[,COLOR]
static void GCIRCLE(PetitComputer p, int x, int y, int r, DefaultValue!(int, false) color) static void GCIRCLE(PetitComputer p, int x, int y, int r, DefaultValue!(int, false) color)
{ {
color.setDefaultValue(p.gcolor); color.setDefaultValue(p.graphic.gcolor);
p.gcircle(p.useGRP, x, y, r, 0, 360, 0, cast(int)color); p.graphic.gcircle(p.graphic.useGRP, x, y, r, 0, 360, 0, cast(int)color);
} }
static void GCIRCLE(PetitComputer p, int x, int y, int r, int sr, int er, DefaultValue!(int, false) flag, DefaultValue!(int, false) color) static void GCIRCLE(PetitComputer p, int x, int y, int r, int sr, int er, DefaultValue!(int, false) flag, DefaultValue!(int, false) color)
{ {
color.setDefaultValue(p.gcolor); color.setDefaultValue(p.graphic.gcolor);
flag.setDefaultValue(0); flag.setDefaultValue(0);
p.gcircle(p.useGRP, x, y, r, sr, er, cast(int)flag, cast(int)color); p.graphic.gcircle(p.graphic.useGRP, x, y, r, sr, er, cast(int)flag, cast(int)color);
} }
static void GCOLOR(PetitComputer p, int color) static void GCOLOR(PetitComputer p, int color)
{ {
p.gcolor = color; p.graphic.gcolor = color;
} }
static void GPRIO(PetitComputer p, int z) static void GPRIO(PetitComputer p, int z)
{ {
p.gprio = z; p.graphic.gprio = z;
} }
static void GPAGE(PetitComputer p, int showPage, int usePage) static void GPAGE(PetitComputer p, int showPage, int usePage)
{ {
p.showGRP = showPage; p.graphic.showGRP = showPage;
p.useGRP = usePage; p.graphic.useGRP = usePage;
} }
static void GPAINT(PetitComputer p, int x, int y, DefaultValue!(int, false) color, DefaultValue!(int, false) color2) static void GPAINT(PetitComputer p, int x, int y, DefaultValue!(int, false) color, DefaultValue!(int, false) color2)
{ {
color.setDefaultValue(p.gcolor); color.setDefaultValue(p.graphic.gcolor);
p.gpaint(p.useGRP, x, y, cast(int)color); p.graphic.gpaint(p.graphic.useGRP, x, y, cast(int)color);
} }
static void BGMPLAY(PetitComputer p, int music) static void BGMPLAY(PetitComputer p, int music)
{ {

View File

@@ -1,103 +0,0 @@
module otya.smilebasic.draw;
import otya.smilebasic.petitcomputer;
import derelict.opengl3.gl;
class Draw
{
PetitComputer petitcom;
this(PetitComputer petitcom)
{
this.petitcom = petitcom;
}
void gpset(int page, int x, int y, uint color)
{
color = PetitComputer.toGLColor(petitcom.GRP[page].textureFormat, color);
glBindTexture(GL_TEXTURE_2D, petitcom.GRP[page].glTexture);
glTexSubImage2D(GL_TEXTURE_2D , 0, x, y, 1, 1, petitcom.GRP[page].textureFormat, GL_UNSIGNED_BYTE, &color);
}
void gline(int page, int x, int y, int x2, int y2, uint color)
{
import std.math;
color = PetitComputer.toGLColor(petitcom.GRP[page].textureFormat, color);
glBindTexture(GL_TEXTURE_2D, petitcom.GRP[page].glTexture);
auto tf = petitcom.GRP[page].textureFormat;
int dx = abs(x2 - x);
int dy = abs(y2 - y);
int sx, sy;
if(x < x2) sx = 1; else sx = -1;
if(y < y2) sy = 1; else sy = -1;
int err = dx - dy;
while(true)
{
if(x < 0 || y < 0 || x >= 512 || y >= 512) break;
glTexSubImage2D(GL_TEXTURE_2D , 0, x, y, 1, 1, tf, GL_UNSIGNED_BYTE, &color);
if(x == x2 && y == y2) break;
int e2 = 2*err;
if(e2 > -dy)
{
err = err - dy;
x = x + sx;
}
if(e2 < dx)
{
err = err + dx;
y = y + sy ;
}
}
}
uint[] graphicBuffer = new uint[512 * 512];
void gfill(int page, int x, int y, int x2, int y2, uint color)
{
import std.algorithm;
import std.math;
if(x < 0 && x2 < 0 || y < 0 && y2 < 0) return;
if(x > 511 && x2 > 511 || y > 511 && y2 > 511) return;
//0<=x<512
x = min(max(x, 0), 511);
y = min(max(y, 0), 511);
x2 = min(max(x2, 0), 511);
y2 = min(max(y2, 0), 511);
if(x2 < x) swap(x, x2);
if(y2 < y) swap(y, y2);
auto w = abs(x2 - x) + 1;//abs
auto h = abs(y2 - y) + 1;
auto size = w * h;
uint* pixels = graphicBuffer.ptr;
color = PetitComputer.toGLColor(petitcom.GRP[page].textureFormat, color);
for(int i = 0; i < size; i++)
{
pixels[i] = color;
}
glBindTexture(GL_TEXTURE_2D, petitcom.GRP[page].glTexture);
glTexSubImage2D(GL_TEXTURE_2D , 0, x, y, w, h, petitcom.GRP[page].textureFormat, GL_UNSIGNED_BYTE, pixels);
}
void gbox(int page, int x, int y, int x2, int y2, uint color)
{
import std.algorithm;
import std.math;
if(x < 0 && x2 < 0 || y < 0 && y2 < 0) return;
if(x > 511 && x2 > 511 || y > 511 && y2 > 511) return;
//0<=x<512
x = min(max(x, 0), 511);
y = min(max(y, 0), 511);
x2 = min(max(x2, 0), 511);
y2 = min(max(y2, 0), 511);
if(x2 < x) swap(x, x2);
if(y2 < y) swap(y, y2);
auto w = abs(x2 - x) + 1;//abs
auto h = abs(y2 - y) + 1;
auto size = max(w, h);
uint* pixels = graphicBuffer.ptr;
color = PetitComputer.toGLColor(petitcom.GRP[page].textureFormat, color);
for(int i = 0; i < size; i++)
{
pixels[i] = color;
}
glBindTexture(GL_TEXTURE_2D, petitcom.GRP[page].glTexture);
glTexSubImage2D(GL_TEXTURE_2D , 0, x, y, w, 1, petitcom.GRP[page].textureFormat, GL_UNSIGNED_BYTE, pixels);
glTexSubImage2D(GL_TEXTURE_2D , 0, x, y2, w, 1, petitcom.GRP[page].textureFormat, GL_UNSIGNED_BYTE, pixels);
glTexSubImage2D(GL_TEXTURE_2D , 0, x, y, 1, h, petitcom.GRP[page].textureFormat, GL_UNSIGNED_BYTE, pixels);
glTexSubImage2D(GL_TEXTURE_2D , 0, x2, y, 1, h, petitcom.GRP[page].textureFormat, GL_UNSIGNED_BYTE, pixels);
}
}

442
SMILEBASIC/graphic.d Normal file
View File

@@ -0,0 +1,442 @@
module otya.smilebasic.graphic;
import derelict.sdl2.sdl;
import derelict.sdl2.image;
import derelict.opengl3.gl;
import derelict.opengl3.gl3;
import otya.smilebasic.petitcomputer;
class Graphic
{
PetitComputer petitcom;
this(PetitComputer p)
{
petitcom = p;
//nnnue
paint.buffer = new uint[512 * 512];
}
bool visibleGRP = true;
private int[2] showPage = [0, 1];
private int[2] usePage = [0, 1];
@property int useGRP()
{
return usePage[petitcom.displaynum];
}
@property int showGRP()
{
return showPage[petitcom.displaynum];
}
@property void useGRP(int page)
{
usePage[petitcom.displaynum] = page;
}
@property void showGRP(int page)
{
showPage[petitcom.displaynum] = page;
}
uint gcolor = -1;
GraphicPage[] GRP;
struct Paint
{
uint[] buffer;
static const MAXSIZE = 1024; /* バッファサイズ */
/* 画面サイズは 1024 X 1024 とする */
static const MINX = 0;
static const MINY = 0;
static const MAXX = 511;
static const MAXY = 511;
struct BufStr {
int lx; /* 領域右端のX座標 */
int rx; /* 領域右端のX座標 */
int y; /* 領域のY座標 */
int oy; /* 親ラインのY座標 */
};
BufStr buff[MAXSIZE]; /* シード登録用バッファ */
BufStr* sIdx, eIdx; /* buffの先頭・末尾ポインタ */
uint point(int x, int y)
{
return buffer.ptr[x + y * 512];
}
void pset(int x, int y, uint col)
{
buffer.ptr[x + y * 512] = col;
}
/*
scanLine : 線分からシードを探索してバッファに登録する
int lx, rx : 線分のX座標の範囲
int y : 線分のY座標
int oy : 親ラインのY座標
unsigned int col : 領域色
*/
void scanLine( int lx, int rx, int y, int oy, uint col )
{
while ( lx <= rx ) {
/* 非領域色を飛ばす */
for ( ; lx < rx ; lx++ )
if ( point( lx, y ) == col ) break;
if ( point( lx, y ) != col ) break;
eIdx.lx = lx;
/* 領域色を飛ばす */
for ( ; lx <= rx ; lx++ )
if ( point( lx, y ) != col ) break;
eIdx.rx = lx - 1;
eIdx.y = y;
eIdx.oy = oy;
if ( ++eIdx == &buff.ptr[MAXSIZE] )
eIdx = buff.ptr;
}
}
/*
paint : 塗り潰し処理(高速版)
int x, y : 開始座標
unsigned int paintCol : 塗り潰す時の色(描画色)
*/
void paint( int x, int y, uint paintCol , out int dx, out int dy, out int dx2, out int dy2)
{
int lx, rx; /* 塗り潰す線分の両端のX座標 */
int ly; /* 塗り潰す線分のY座標 */
int oy; /* 親ラインのY座標 */
int i;
uint col = point( x, y ); /* 閉領域の色(領域色) */
dx = int.max, dy = int.max, dx2 = int.min, dy2 = int.min;
if ( col == paintCol ) return; /* 領域色と描画色が等しければ処理不要 */
sIdx = buff.ptr;
eIdx = buff.ptr + 1;
sIdx.lx = sIdx.rx = x;
sIdx.y = sIdx.oy = y;
do {
lx = sIdx.lx;
rx = sIdx.rx;
ly = sIdx.y;
oy = sIdx.oy;
int lxsav = lx - 1;
int rxsav = rx + 1;
if ( ++sIdx == &buff.ptr[MAXSIZE] ) sIdx = buff.ptr;
/* 処理済のシードなら無視 */
if ( point( lx, ly ) != col )
continue;
/* 右方向の境界を探す */
while ( rx < MAXX ) {
if ( point( rx + 1, ly ) != col ) break;
rx++;
}
/* 左方向の境界を探す */
while ( lx > MINX ) {
if ( point( lx - 1, ly ) != col ) break;
lx--;
}
import std.algorithm;
dy = min(dy, ly);
dy2 = max(dy2, ly);
dx = min(dx, lx);
dx2 = max(dx2, rx);
//
/* lx-rxの線分を描画 */
for ( i = lx; i <= rx; i++ ) pset( i, ly, paintCol );
/* 真上のスキャンラインを走査する */
if ( ly - 1 >= MINY ) {
if ( ly - 1 == oy ) {
scanLine( lx, lxsav, ly - 1, ly, col );
scanLine( rxsav, rx, ly - 1, ly, col );
} else {
scanLine( lx, rx, ly - 1, ly, col );
}
}
/* 真下のスキャンラインを走査する */
if ( ly + 1 <= MAXY ) {
if ( ly + 1 == oy ) {
scanLine( lx, lxsav, ly + 1, ly, col );
scanLine( rxsav, rx, ly + 1, ly, col );
} else {
scanLine( lx, rx, ly + 1, ly, col );
}
}
} while ( sIdx != eIdx );
}
void gpaintBuffer(uint* pixels, int x, int y, uint color, GLenum tf)
{
int dx, dy, dx2, dy2;
paint(x, y, color, dx, dy, dx2, dy2);
if(dx == int.max) return;
int h = dy2 - dy;
glTexSubImage2D(GL_TEXTURE_2D , 0, 0, dy, 512, h, tf, GL_UNSIGNED_BYTE, pixels + (dy * 512));
// glDrawPixels(512, dy2, tf, GL_UNSIGNED_BYTE, buffer.ptr);
}
}
Paint paint;
void drawCircle(int x, int y, int r, int startr, int endr, int flag)
{
import std.math : sin, cos, PI;
int count = r;
glBegin(GL_LINE_LOOP);
for (int i = 0; i <= r; i++)
{
//float a = i * (360f / r);
glVertex2f(sin(cast(float)i / count * 2f * PI) * r + x, cos(cast(float)i / count * 2f * PI) * r + y);
}
glEnd();
}
void draw()
{
if(!drawMessageLength) return;
drawflag = true;
//betuni kouzoutai demo sonnnani sokudo kawaranasasou
auto len = drawMessageLength;
int s = petitcom.renderstartpos;
GLint old;
auto a = &glBindFramebuffer;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old);
int oldpage = drawMessageQueue[0].page;
glBindFramebufferEXT(GL_FRAMEBUFFER, this.GRP[oldpage].buffer);
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glDisable(GL_DEPTH_TEST);
//glAlphaFunc(GL_GEQUAL, 0.0);
void chScreen(int x, int y, int w, int h)
{
glViewport(x, y, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -256, 1024);//wakaranai
}
chScreen(0, 0, 511, 511);
DrawType dt;
auto start = SDL_GetTicks();
int i = s;
static const size = 255.5f;
for(; i < len; i++)
{
DrawMessage dm = drawMessageQueue[i];
if(oldpage != dm.page)
{
oldpage = dm.page;
glBindFramebufferEXT(GL_FRAMEBUFFER, this.GRP[oldpage].buffer);
}
switch(dm.type)
{
case DrawType.PSET:
glBegin(GL_POINTS);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f(dm.x, dm.y);
glEnd();
break;
case DrawType.LINE:
{
glBegin(GL_LINES);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f(dm.x, dm.y);
glVertex2f(dm.x2, dm.y2);
//glFlush();
glEnd();
}
break;
case DrawType.FILL:
{
glBegin(GL_QUADS);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f(dm.x, dm.y);
glVertex2f(dm.x, dm.y2);
glVertex2f(dm.x2, dm.y2);
glVertex2f(dm.x2, dm.y);
glEnd();
}
break;
case DrawType.BOX:
{
glBegin(GL_LINE_LOOP);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f(dm.x, dm.y);
glVertex2f(dm.x, dm.y2);
glVertex2f(dm.x2, dm.y2);
glVertex2f(dm.x2, dm.y);
glEnd();
}
break;
case DrawType.PAINT:
{
glBindTexture(GL_TEXTURE_2D, GRP[oldpage].glTexture);
if(dt != DrawType.PAINT)
{
glFinish();
//glGetTexImage(GL_TEXTURE_2D,0,GRP[oldpage].textureFormat,GL_UNSIGNED_BYTE,buffer.ptr);
glReadPixels(0, 0, 512, 512, GRP[oldpage].textureFormat, GL_UNSIGNED_BYTE, paint.buffer.ptr);
}
paint.gpaintBuffer(paint.buffer.ptr, dm.x, dm.y, dm.color, GRP[oldpage].textureFormat);
//gpaintBufferExW(oldpage, dm.x, dm.y, dm.color);
if(SDL_GetTicks() - start >= 16 && i != len - 1)
{
s = i + 1;
goto brk;
}
}
break;
case DrawType.CIRCLE:
{
glColor4ubv(cast(ubyte*)&dm.color);
drawCircle(dm.x, dm.y, dm.circle.r, dm.circle.startr, dm.circle.endr, dm.circle.flag);
}
break;
default:
}
dt = dm.type;
}
brk:
if(i == len)
{
petitcom.renderstartpos = 0;
drawMessageLength = 0;
}
else
{
petitcom.renderstartpos = s;
}
glBindFramebufferEXT(GL_FRAMEBUFFER, old);
glEnable(GL_DEPTH_TEST);
drawflag = false;
glEnable(GL_ALPHA_TEST);
}
enum DrawType
{
CLEAR,
PSET,
LINE,
FILL,
BOX,
CIRCLE,
TRI,
PAINT,
}
struct Circle
{
short r, startr, endr;
short flag;
}
struct DrawMessage
{
DrawType type;
byte page;
short x;
short y;
uint color;
short x2;
short y2;
Circle circle;
//
}
static const int dmqqueuelen = 8192;
DrawMessage[] drawMessageQueue = new DrawMessage[dmqqueuelen];
int drawMessageLength;
bool drawflag;
void sendDrawMessage(DrawMessage dm)
{
//grpmutex.lock();
//scope(exit)
// grpmutex.unlock();
if(drawMessageLength >= dmqqueuelen)
{
while(drawMessageLength)
{
SDL_Delay(1);
}
}
while(drawflag){}
dm.color = petitcom.toGLColor(this.GRP[0].textureFormat, dm.color & 0xFFF8F8F8);
drawMessageQueue[drawMessageLength] = dm;
drawMessageLength++;
}
void sendDrawMessage(DrawType type, byte page, short x, short y, uint color)
{
DrawMessage dm;
dm.type = type;
dm.page = page;
dm.x = x;
dm.y = y;
dm.color = color;
sendDrawMessage(dm);
}
void sendDrawMessage(DrawType type, byte page, short x, short y, short x2, short y2, uint color)
{
DrawMessage dm;
dm.type = type;
dm.page = page;
dm.x = x;
dm.y = y;
dm.x2 = x2;
dm.y2 = y2;
dm.color = color;
sendDrawMessage(dm);
}
//TODO:範囲チェック
void gpset(int page, int x, int y, uint color)
{
sendDrawMessage(DrawType.PSET, cast(byte)page, cast(short)x, cast(short)y, color);
}
void gline(int page, int x, int y, int x2, int y2, uint color)
{
sendDrawMessage(DrawType.LINE, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
}
void gbox(int page, int x, int y, int x2, int y2, uint color)
{
sendDrawMessage(DrawType.BOX, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
}
void gfill(int page, int x, int y, int x2, int y2, uint color)
{
sendDrawMessage(DrawType.FILL, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
}
void gpaint(int page, int x, int y, uint color)
{
sendDrawMessage(DrawType.PAINT, cast(byte)page, cast(short)x, cast(short)y, color);
}
void gcircle(int page, int x, int y, int r, int startr, int endr, int flag, uint color)
{
DrawMessage dm;
dm.page = cast(byte)page;
dm.x = cast(short)x;
dm.y = cast(short)y;
dm.circle.r = cast(short)r;
dm.circle.startr = cast(short)startr;
dm.circle.endr = cast(short)endr;
dm.circle.flag = cast(short)flag;
dm.color = color;
dm.type = DrawType.CIRCLE;
sendDrawMessage(dm);
}
int gprio;
void render(int display, float w, float h)
{
float z = gprio;
glColor3f(1.0, 1.0, 1.0);
glBindTexture(GL_TEXTURE_2D, GRP[showPage[display]].glTexture);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0 / 512f - 1 , h / 512f - 1);
glVertex3f(0, h, z);
glTexCoord2f(0 / 512f - 1, 0 / 512f - 1);
glVertex3f(0, 0, z);
glTexCoord2f(w / 512f - 1, 0 / 512f - 1);
glVertex3f(w, 0, z);
glTexCoord2f(w / 512f - 1, h / 512f - 1);
glVertex3f(w, h, z);
glEnd();
//glFlush();
}
}

View File

@@ -17,6 +17,7 @@ import otya.smilebasic.bg;
import otya.smilebasic.parser; import otya.smilebasic.parser;
import otya.smilebasic.project; import otya.smilebasic.project;
import otya.smilebasic.console; import otya.smilebasic.console;
import otya.smilebasic.graphic;
const static rot_test_deg = 45f; const static rot_test_deg = 45f;
const static rot_test_x = 0f; const static rot_test_x = 0f;
const static rot_test_y = 1f; const static rot_test_y = 1f;
@@ -185,27 +186,6 @@ class PetitComputer
return SDL_Color(r >> 5 << 5, g >> 5 << 5, b >> 5 << 5, a == 255 ? 255 : 0); return SDL_Color(r >> 5 << 5, g >> 5 << 5, b >> 5 << 5, a == 255 ? 255 : 0);
} }
Button button; Button button;
bool visibleGRP = true;
private int[2] showPage = [0, 1];
private int[2] usePage = [0, 1];
@property int useGRP()
{
return usePage[displaynum];
}
@property int showGRP()
{
return showPage[displaynum];
}
@property void useGRP(int page)
{
usePage[displaynum] = page;
}
@property void showGRP(int page)
{
showPage[displaynum] = page;
}
uint gcolor = -1;
GraphicPage[] GRP;
GraphicPage createGRPF(string file) GraphicPage createGRPF(string file)
{ {
SDL_RWops* stream = SDL_RWFromFile(toStringz(file), toStringz("rb")); SDL_RWops* stream = SDL_RWFromFile(toStringz(file), toStringz("rb"));
@@ -345,6 +325,7 @@ class PetitComputer
vsyncCount = 0; vsyncCount = 0;
vsyncFrame = f; vsyncFrame = f;
} }
Graphic graphic;
Mutex keybuffermutex; Mutex keybuffermutex;
int keybufferpos; int keybufferpos;
int keybufferlen; int keybufferlen;
@@ -386,152 +367,6 @@ class PetitComputer
} }
Mutex grpmutex; Mutex grpmutex;
int displaynum; int displaynum;
struct Paint
{
uint[] buffer;
static const MAXSIZE = 1024; /* バッファサイズ */
/* 画面サイズは 1024 X 1024 とする */
static const MINX = 0;
static const MINY = 0;
static const MAXX = 511;
static const MAXY = 511;
struct BufStr {
int lx; /* 領域右端のX座標 */
int rx; /* 領域右端のX座標 */
int y; /* 領域のY座標 */
int oy; /* 親ラインのY座標 */
};
BufStr buff[MAXSIZE]; /* シード登録用バッファ */
BufStr* sIdx, eIdx; /* buffの先頭・末尾ポインタ */
uint point(int x, int y)
{
return buffer.ptr[x + y * 512];
}
void pset(int x, int y, uint col)
{
buffer.ptr[x + y * 512] = col;
}
/*
scanLine : 線分からシードを探索してバッファに登録する
int lx, rx : 線分のX座標の範囲
int y : 線分のY座標
int oy : 親ラインのY座標
unsigned int col : 領域色
*/
void scanLine( int lx, int rx, int y, int oy, uint col )
{
while ( lx <= rx ) {
/* 非領域色を飛ばす */
for ( ; lx < rx ; lx++ )
if ( point( lx, y ) == col ) break;
if ( point( lx, y ) != col ) break;
eIdx.lx = lx;
/* 領域色を飛ばす */
for ( ; lx <= rx ; lx++ )
if ( point( lx, y ) != col ) break;
eIdx.rx = lx - 1;
eIdx.y = y;
eIdx.oy = oy;
if ( ++eIdx == &buff.ptr[MAXSIZE] )
eIdx = buff.ptr;
}
}
/*
paint : 塗り潰し処理(高速版)
int x, y : 開始座標
unsigned int paintCol : 塗り潰す時の色(描画色)
*/
void paint( int x, int y, uint paintCol , out int dx, out int dy, out int dx2, out int dy2)
{
int lx, rx; /* 塗り潰す線分の両端のX座標 */
int ly; /* 塗り潰す線分のY座標 */
int oy; /* 親ラインのY座標 */
int i;
uint col = point( x, y ); /* 閉領域の色(領域色) */
dx = int.max, dy = int.max, dx2 = int.min, dy2 = int.min;
if ( col == paintCol ) return; /* 領域色と描画色が等しければ処理不要 */
sIdx = buff.ptr;
eIdx = buff.ptr + 1;
sIdx.lx = sIdx.rx = x;
sIdx.y = sIdx.oy = y;
do {
lx = sIdx.lx;
rx = sIdx.rx;
ly = sIdx.y;
oy = sIdx.oy;
int lxsav = lx - 1;
int rxsav = rx + 1;
if ( ++sIdx == &buff.ptr[MAXSIZE] ) sIdx = buff.ptr;
/* 処理済のシードなら無視 */
if ( point( lx, ly ) != col )
continue;
/* 右方向の境界を探す */
while ( rx < MAXX ) {
if ( point( rx + 1, ly ) != col ) break;
rx++;
}
/* 左方向の境界を探す */
while ( lx > MINX ) {
if ( point( lx - 1, ly ) != col ) break;
lx--;
}
import std.algorithm;
dy = min(dy, ly);
dy2 = max(dy2, ly);
dx = min(dx, lx);
dx2 = max(dx2, rx);
//
/* lx-rxの線分を描画 */
for ( i = lx; i <= rx; i++ ) pset( i, ly, paintCol );
/* 真上のスキャンラインを走査する */
if ( ly - 1 >= MINY ) {
if ( ly - 1 == oy ) {
scanLine( lx, lxsav, ly - 1, ly, col );
scanLine( rxsav, rx, ly - 1, ly, col );
} else {
scanLine( lx, rx, ly - 1, ly, col );
}
}
/* 真下のスキャンラインを走査する */
if ( ly + 1 <= MAXY ) {
if ( ly + 1 == oy ) {
scanLine( lx, lxsav, ly + 1, ly, col );
scanLine( rxsav, rx, ly + 1, ly, col );
} else {
scanLine( lx, rx, ly + 1, ly, col );
}
}
} while ( sIdx != eIdx );
}
void gpaintBuffer(uint* pixels, int x, int y, uint color, GLenum tf)
{
int dx, dy, dx2, dy2;
paint(x, y, color, dx, dy, dx2, dy2);
if(dx == int.max) return;
int h = dy2 - dy;
glTexSubImage2D(GL_TEXTURE_2D , 0, 0, dy, 512, h, tf, GL_UNSIGNED_BYTE, pixels + (dy * 512));
// glDrawPixels(512, dy2, tf, GL_UNSIGNED_BYTE, buffer.ptr);
}
}
Paint paint;
int renderstartpos; int renderstartpos;
void chScreen(int x, int y, int w, int h) void chScreen(int x, int y, int w, int h)
{ {
@@ -540,142 +375,6 @@ class PetitComputer
glLoadIdentity(); glLoadIdentity();
glOrtho(0, w, h, 0, 1024, -2048); glOrtho(0, w, h, 0, 1024, -2048);
} }
void drawCircle(int x, int y, int r, int startr, int endr, int flag)
{
import std.math : sin, cos, PI;
int count = r;
glBegin(GL_LINE_LOOP);
for (int i = 0; i <= r; i++)
{
//float a = i * (360f / r);
glVertex2f(sin(cast(float)i / count * 2f * PI) * r + x, cos(cast(float)i / count * 2f * PI) * r + y);
}
glEnd();
}
void renderGraphic()
{
if(!drawMessageLength) return;
drawflag = true;
//betuni kouzoutai demo sonnnani sokudo kawaranasasou
auto len = drawMessageLength;
int s = renderstartpos;
GLint old;
auto a = & glBindFramebuffer;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old);
int oldpage = drawMessageQueue[0].page;
glBindFramebufferEXT(GL_FRAMEBUFFER, this.GRP[oldpage].buffer);
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glDisable(GL_DEPTH_TEST);
//glAlphaFunc(GL_GEQUAL, 0.0);
void chScreen(int x, int y, int w, int h)
{
glViewport(x, y, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -256, 1024);//wakaranai
}
chScreen(0, 0, 511, 511);
DrawType dt;
auto start = SDL_GetTicks();
int i = s;
static const size = 255.5f;
for(; i < len; i++)
{
DrawMessage dm = drawMessageQueue[i];
if(oldpage != dm.page)
{
oldpage = dm.page;
glBindFramebufferEXT(GL_FRAMEBUFFER, this.GRP[oldpage].buffer);
}
switch(dm.type)
{
case DrawType.PSET:
glBegin(GL_POINTS);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f(dm.x, dm.y);
glEnd();
//draw.gpset(dm.page, dm.x, dm.y ,dm.color);
break;
case DrawType.LINE:
{
glBegin(GL_LINES);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f(dm.x, dm.y);
glVertex2f(dm.x2, dm.y2);
//glFlush();
glEnd();
}
//draw.gline(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
break;
case DrawType.FILL:
{
glBegin(GL_QUADS);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f(dm.x, dm.y);
glVertex2f(dm.x, dm.y2);
glVertex2f(dm.x2, dm.y2);
glVertex2f(dm.x2, dm.y);
glEnd();
}
//draw.gfill(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
break;
case DrawType.BOX:
{
glBegin(GL_LINE_LOOP);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f(dm.x, dm.y);
glVertex2f(dm.x, dm.y2);
glVertex2f(dm.x2, dm.y2);
glVertex2f(dm.x2, dm.y);
glEnd();
}
//draw.gbox(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
break;
case DrawType.PAINT:
{
glBindTexture(GL_TEXTURE_2D, GRP[oldpage].glTexture);
if(dt != DrawType.PAINT)
{
glFinish();
//glGetTexImage(GL_TEXTURE_2D,0,GRP[oldpage].textureFormat,GL_UNSIGNED_BYTE,buffer.ptr);
glReadPixels(0, 0, 512, 512, GRP[oldpage].textureFormat, GL_UNSIGNED_BYTE, paint.buffer.ptr);
}
paint.gpaintBuffer(paint.buffer.ptr, dm.x, dm.y, dm.color, GRP[oldpage].textureFormat);
//gpaintBufferExW(oldpage, dm.x, dm.y, dm.color);
if(SDL_GetTicks() - start >= 16 && i != len - 1)
{
s = i + 1;
goto brk;
}
}
break;
case DrawType.CIRCLE:
{
glColor4ubv(cast(ubyte*)&dm.color);
drawCircle(dm.x, dm.y, dm.circle.r, dm.circle.startr, dm.circle.endr, dm.circle.flag);
}
break;
default:
}
dt = dm.type;
}
brk:
if(i == len)
{
renderstartpos = 0;
drawMessageLength = 0;
}
else
{
renderstartpos = s;
}
glBindFramebufferEXT(GL_FRAMEBUFFER, old);
glEnable(GL_DEPTH_TEST);
drawflag = false;
glEnable(GL_ALPHA_TEST);
}
Button[] buttonTable; Button[] buttonTable;
Sprite sprite; Sprite sprite;
int xscreenmode = 0; int xscreenmode = 0;
@@ -721,19 +420,18 @@ class PetitComputer
{ {
try try
{ {
paint.buffer = new uint[512 * 512];
DerelictSDL2.load(); DerelictSDL2.load();
DerelictSDL2Image.load(); DerelictSDL2Image.load();
console.GRPF = createGRPF(fontFile); console.GRPF = createGRPF(fontFile);
GRP = new GraphicPage[6]; graphic.GRP = new GraphicPage[6];
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++)
{ {
GRP[i] = createEmptyPage(); graphic.GRP[i] = createEmptyPage();
} }
sppage = 4; sppage = 4;
GRP[4] = createGRPF(spriteFile); graphic.GRP[4] = createGRPF(spriteFile);
bgpage = 5; bgpage = 5;
GRP[5] = createGRPF(BGFile); graphic.GRP[5] = createGRPF(BGFile);
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
DerelictGL.load(); DerelictGL.load();
@@ -809,7 +507,7 @@ class PetitComputer
} }
int loopcnt; int loopcnt;
DerelictGL3.reload(); DerelictGL3.reload();
foreach(g; GRP) foreach(g; graphic.GRP)
{ {
g.createTexture(renderer); g.createTexture(renderer);
g.createBuffer(); g.createBuffer();
@@ -842,7 +540,7 @@ class PetitComputer
} }
} }
glLoadIdentity(); glLoadIdentity();
renderGraphic(); graphic.draw();
chScreen(0, 0, 400, 240); chScreen(0, 0, 400, 240);
if(xscreenmode == 1) if(xscreenmode == 1)
{ {
@@ -865,16 +563,16 @@ class PetitComputer
} }
if(xscreenmode == 2) if(xscreenmode == 2)
{ {
renderGraphicPage(0, 320, 480); graphic.render(0, 320, 480);
} }
else else
{ {
renderGraphicPage(0, 400, 240); graphic.render(0, 400, 240);
} }
if(xscreenmode == 1) if(xscreenmode == 1)
{ {
chScreen(40, 0, 320, 240); chScreen(40, 0, 320, 240);
renderGraphicPage(1, 320, 240); graphic.render(1, 320, 240);
chScreen(0, 240, 400, 240); chScreen(0, 240, 400, 240);
} }
if(xscreenmode == 2) if(xscreenmode == 2)
@@ -887,7 +585,7 @@ class PetitComputer
} }
version(test) glLoadIdentity(); version(test) glLoadIdentity();
version(test) glRotatef(rot_test_deg, rot_test_x, rot_test_y, rot_test_z); version(test) glRotatef(rot_test_deg, rot_test_x, rot_test_y, rot_test_z);
glBindTexture(GL_TEXTURE_2D, GRP[bgpage].glTexture); glBindTexture(GL_TEXTURE_2D, graphic.GRP[bgpage].glTexture);
if(xscreenmode == 2) if(xscreenmode == 2)
{ {
for(int i = 0; i < bgmax; i++) for(int i = 0; i < bgmax; i++)
@@ -1030,6 +728,7 @@ class PetitComputer
slot = new Slot[5]; slot = new Slot[5];
keybuffer = new Key[128]; keybuffer = new Key[128];
init(); init();
graphic = new Graphic(this);
consolem = new Mutex(); consolem = new Mutex();
keybuffermutex = new Mutex(); keybuffermutex = new Mutex();
grpmutex = new Mutex(); grpmutex = new Mutex();
@@ -1490,129 +1189,4 @@ class PetitComputer
{ {
return a << 24 | r << 16 | g << 8 | b; return a << 24 | r << 16 | g << 8 | b;
} }
enum DrawType
{
CLEAR,
PSET,
LINE,
FILL,
BOX,
CIRCLE,
TRI,
PAINT,
}
struct Circle
{
short r, startr, endr;
short flag;
}
struct DrawMessage
{
DrawType type;
byte page;
short x;
short y;
uint color;
short x2;
short y2;
Circle circle;
//
}
static const int dmqqueuelen = 8192;
DrawMessage[] drawMessageQueue = new DrawMessage[dmqqueuelen];
int drawMessageLength;
bool drawflag;
void sendDrawMessage(DrawMessage dm)
{
//grpmutex.lock();
//scope(exit)
// grpmutex.unlock();
if(drawMessageLength >= dmqqueuelen)
{
while(drawMessageLength)
{
SDL_Delay(1);
}
}
while(drawflag){}
dm.color = toGLColor(this.GRP[0].textureFormat, dm.color & 0xFFF8F8F8);
drawMessageQueue[drawMessageLength] = dm;
drawMessageLength++;
}
void sendDrawMessage(DrawType type, byte page, short x, short y, uint color)
{
DrawMessage dm;
dm.type = type;
dm.page = page;
dm.x = x;
dm.y = y;
dm.color = color;
sendDrawMessage(dm);
}
void sendDrawMessage(DrawType type, byte page, short x, short y, short x2, short y2, uint color)
{
DrawMessage dm;
dm.type = type;
dm.page = page;
dm.x = x;
dm.y = y;
dm.x2 = x2;
dm.y2 = y2;
dm.color = color;
sendDrawMessage(dm);
}
//TODO:範囲チェック
void gpset(int page, int x, int y, uint color)
{
sendDrawMessage(DrawType.PSET, cast(byte)page, cast(short)x, cast(short)y, color);
}
void gline(int page, int x, int y, int x2, int y2, uint color)
{
sendDrawMessage(DrawType.LINE, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
}
void gbox(int page, int x, int y, int x2, int y2, uint color)
{
sendDrawMessage(DrawType.BOX, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
}
void gfill(int page, int x, int y, int x2, int y2, uint color)
{
sendDrawMessage(DrawType.FILL, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
}
void gpaint(int page, int x, int y, uint color)
{
sendDrawMessage(DrawType.PAINT, cast(byte)page, cast(short)x, cast(short)y, color);
}
void gcircle(int page, int x, int y, int r, int startr, int endr, int flag, uint color)
{
DrawMessage dm;
dm.page = cast(byte)page;
dm.x = cast(short)x;
dm.y = cast(short)y;
dm.circle.r = cast(short)r;
dm.circle.startr = cast(short)startr;
dm.circle.endr = cast(short)endr;
dm.circle.flag = cast(short)flag;
dm.color = color;
dm.type = DrawType.CIRCLE;
sendDrawMessage(dm);
}
int gprio;
void renderGraphicPage(int display, float w, float h)
{
float z = gprio;
glColor3f(1.0, 1.0, 1.0);
glBindTexture(GL_TEXTURE_2D, GRP[showPage[display]].glTexture);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0 / 512f - 1 , h / 512f - 1);
glVertex3f(0, h, z);
glTexCoord2f(0 / 512f - 1, 0 / 512f - 1);
glVertex3f(0, 0, z);
glTexCoord2f(w / 512f - 1, 0 / 512f - 1);
glVertex3f(w, 0, z);
glTexCoord2f(w / 512f - 1, h / 512f - 1);
glVertex3f(w, h, z);
glEnd();
//glFlush();
}
} }

View File

@@ -625,7 +625,7 @@ class Sprite
dish2 = 480f; dish2 = 480f;
dis = -1; dis = -1;
} }
auto texture = petitcom.GRP[petitcom.sppage].glTexture; auto texture = petitcom.graphic.GRP[petitcom.sppage].glTexture;
float aspect = disw2 / dish2; float aspect = disw2 / dish2;
float z = -0.01f; float z = -0.01f;
int spmax = petitcom.xscreenmode == 1 ? this.spmax : 512;//XSCREENが2,3じゃないと下画面は描画しない int spmax = petitcom.xscreenmode == 1 ? this.spmax : 512;//XSCREENが2,3じゃないと下画面は描画しない