 Joined: Jun 2013
Posts: 2
|
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.
/********************************************************************************\ ** ** ** 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); }
|