This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
Pages: 1
1
Function Peer Review / sprite_create_from_screen
« on: June 18, 2013, 02:52:23 pm »
Hello, lovely people.
I put this together for you. The only items that need implementation are the "smooth" and "preload" params, but this is ready to run.
Enjoy.
I put this together for you. The only items that need implementation are the "smooth" and "preload" params, but this is ready to run.
Enjoy.
Code: [Select]
/********************************************************************************\
** **
** Copyright (C) 2013 Seeker **
** **
** This file is a part of the ENIGMA Development Environment. **
** **
** **
** ENIGMA is free software: you can redistribute it and/or modify it under the **
** terms of the GNU General Public License as published by the Free Software **
** Foundation, version 3 of the license or any later version. **
** **
** This application and its source code is distributed AS-IS, WITHOUT ANY **
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS **
** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more **
** details. **
** **
** You should have recieved a copy of the GNU General Public License along **
** with this code. If not, see <http://www.gnu.org/licenses/> **
** **
** ENIGMA is an environment designed to create games and other programs with a **
** high-level, fully compilable language. Developers of ENIGMA or anything **
** associated with ENIGMA are in no way responsible for its users or **
** applications created by its users, or damages caused by the environment **
** or programs made in the environment. **
** **
\********************************************************************************/
// Includes
#include <string.h>
#include "Universal_System/nlpo2.h"
// Declarations
// gm7-
int sprite_create_from_screen(unsigned int x, unsigned int y, unsigned int w, unsigned int h, bool precise, bool transparent, bool smooth, bool preload, int xorig, int yorig);
// gm8+
int sprite_create_from_screen(unsigned int x, unsigned int y, unsigned int w, unsigned int h, bool removeback, bool smooth, int xorig, int yorig);
// Definitions
// NOTE: The only items that need implementation are the "smooth" and "preload" params
int sprite_create_from_screen(unsigned int x, unsigned int y, unsigned int w, unsigned int h, bool precise, bool transparent, bool smooth, bool preload, int xorig, int yorig)
{
static bool viewRedrawHack = false; // currently needed so this function can safely be called in a Draw event, since this function forces a screen_redraw() if view_enabled
if (view_enabled && viewRedrawHack) return -1;
//
w = max(w,1);
h = max(h,1);
int wFull = nlpo2dc(w) + 1,
hFull = nlpo2dc(h) + 1,
stride = wFull * 4;
//
unsigned char * swapline = new unsigned char[stride](),
* pxdata = new unsigned char[stride*hFull]();
if (!swapline || !pxdata) return -1;
//
int viewportData[4];
glGetIntegerv(GL_VIEWPORT, viewportData);
if (view_enabled) // hacking views like the NSA
{
bool viewVisPrev[8];
for (int i = 0; i < 8; i++)
{
viewVisPrev[i] = view_visible[i];
view_visible[i] = (i == 0);
}
int wview0Prev = view_wview,
hview0Prev = view_hview;
view_wview = /*window_get_width()*/viewportData[2];
view_hview = /*window_get_height()*/viewportData[3];
viewRedrawHack = true;
screen_redraw();
viewRedrawHack = false;
view_wview = wview0Prev;
view_hview = hview0Prev;
for (int i = 0; i < 8; i++) view_visible[i] = viewVisPrev[i];
}
glReadPixels(x, /*window_get_height()*/viewportData[3] - y - hFull, wFull, hFull, GL_RGBA, GL_UNSIGNED_BYTE, pxdata);
//
for (int row = 0; row < hFull/2; row++) // flip pixels vertically
{
memcpy(swapline, pxdata + row*stride, stride);
memcpy(pxdata + row*stride, pxdata + (hFull-row-1)*stride, stride);
memcpy(pxdata + (hFull-row-1)*stride, swapline, stride);
}
delete[] swapline;
//
int bbl = 0,
bbt = 0,
bbr = w - 1,
bbb = h - 1;
if (transparent)
{
unsigned char* pxdataTrans = &pxdata[(h-1)*stride]; // transparency pixel data (bottom-left pixel)
bool bblGot = false,
bbtGot = false,
bbrGot = false,
bbbGot = false;
// remove transparent color, and get bbox top and bottom
for (int yy = 0; yy < h; yy++)
{
bool bbtRowEmpty = true,
bbbRowEmpty = true;
for (int xx = 0; xx < w; xx++)
{
int xo = xx*4,
bbtOffset = yy*stride + xo;
if (memcmp(&pxdata[bbtOffset], pxdataTrans, 3) == 0) pxdata[bbtOffset+3] = 0; // a transparent pixel
else bbtRowEmpty = false;
if (!bbbGot && memcmp(&pxdata[(h-1-yy)*stride + xo], pxdataTrans, 3) != 0) bbbRowEmpty = false;
}
if (!bbtGot)
{
if (bbtRowEmpty) bbt++;
else bbtGot = true;
}
if (!bbbGot)
{
if (bbbRowEmpty) bbb--;
else bbbGot = true;
}
}
// now just get bbox left and right
for (int xx = 0; xx < w; xx++)
{
bool bblColEmpty = true,
bbrColEmpty = true;
for (int yy = 0; yy < h; yy++)
{
int xo = xx*4 + 3;
if (!bblGot && pxdata[yy*stride + xo] != 0) bblColEmpty = false;
if (!bbrGot && pxdata[(h-1-yy)*stride + xo] != 0) bbrColEmpty = false;
}
if (!bblGot)
{
if (bblColEmpty) bbl++;
else bblGot = true;
}
if (!bbrGot)
{
if (bbrColEmpty) bbr--;
else bbrGot = true;
}
if (bblGot && bbrGot) break;
}
// if the entire image is transparent, doing this to keep bboxes from being off by 1 pixel
bbl = min(bbl, w - 1);
bbt = min(bbt, h - 1);
bbr = max(bbr, 0);
bbb = max(bbb, 0);
}
// show_message("l: " + string(bbl) + " t: " + string(bbt) + " r: " + string(bbr) + " b: " + string(bbb));
// mostly sprite_add_to_index() code from spritestruct.cpp follows, so may want to refactor
enigma::spritestructarray_reallocate();
enigma::sprite *ns = enigma::spritestructarray[enigma::sprite_idmax] = new enigma::sprite();
// if (!ns) return -1; //
ns->id = enigma::sprite_idmax;
ns->subcount = 1;
ns->width = w;
ns->height = h;
ns->bbox.bottom = bbb;
ns->bbox.left = bbl;
ns->bbox.top = bbt;
ns->bbox.right = bbr;
ns->bbox_relative.bottom = bbb - yorig;
ns->bbox_relative.left = bbl - xorig;
ns->bbox_relative.top = bbt - yorig;
ns->bbox_relative.right = bbr - xorig;
ns->xoffset = (int)xorig;
ns->yoffset = (int)yorig;
ns->texturearray = new int[1];
ns->texturearray[0] = enigma::graphics_create_texture(wFull, hFull, pxdata);
ns->texbordxarray = new double[1];
ns->texbordxarray[0] = (double) w/wFull;
ns->texbordyarray = new double[1];
ns->texbordyarray[0] = (double) h/hFull;
ns->colldata = new void*[1];
enigma::collision_type coll_type = precise ? enigma::ct_precise : enigma::ct_bbox;
ns->colldata[0] = get_collision_mask(ns, (unsigned char *)pxdata, coll_type);
delete[] pxdata;
//
return enigma::sprite_idmax++;
}
inline int sprite_create_from_screen(unsigned int x, unsigned int y, unsigned int w, unsigned int h, bool removeback, bool smooth, int xorig, int yorig)
{
return sprite_create_from_screen(x, y, w, h, /*precise*/removeback, /*transparent*/removeback, smooth, /*preload*/true, xorig, yorig);
}
Pages: 1