Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************/
- /******************************************************************************/
- //"2024-11-21\src\kit_sdl2\kit_SoundEngine_mixTracks.cpp":
- #include "_kit_common.hpp"
- //lower clip's volume to 0 within 10ms if speed reaches 0
- #define speed0VolDeltaMS (10.0f)
- #define MUTEX_PTR ((SDL_mutex*)_lock)
- namespace kit {
- /******************************************************************************/
- #define HANDLE_LOOP \
- /* loop handling (or end-of-clip handling i guess) */ \
- if(trk.position >= loopEnd){ /* audio clip finished loop */ \
- if(!trk.loops){ trk.stopping = true; break; } /* mark as inactive and break */ \
- if(trk.loops != KIT_U16_MAX) --trk.loops; /* decrement loops (unless infinite) */ \
- while(trk.position >= loopEnd) \
- trk.position -= loopDifference; /* jump back to the loop's starting point */ \
- \
- } else if(trk.position < 0){ /* if clip has yet to start playing */ \
- if(trk.position < -trk.spd_old){ \
- trk.position += trk.spd_old; /* step forward by current speed */ \
- continue; \
- } else { /* if position >= -speed, the clip should start on this sample */ \
- trk.position = 0.0; /* make sure clip starts at exactly 0 */ \
- } \
- \
- }
- #define HANDLE_SPEED_UPDATE \
- /* change old and new speed by speedDelta */ \
- f64 currentSpeedDelta = track.spdDelta; \
- trk.spd_old += currentSpeedDelta; \
- trk.spd_new += currentSpeedDelta; \
- \
- t += t_inc; /* raise interpolation t value */ \
- \
- /* start rapid fade out if clip's new speed <= 0 */ \
- if(LERP2(trk.spd_old, trk.spd_new, t) <= 0.0){ \
- trk.spd_old = trk.spd_new = 0.0; \
- /* volDelta is sorta volatile, so that might need to be accounted for... */ \
- track.volDelta = speed0VDelta; \
- }
- /******************************************************************************/
- static inline f32 linearSmpMono(const f32* src, f64 position,
- u64 loopEnd = KIT_U64_MAX)
- {
- const u64 intPosition = (u64)position;
- const f32 modPosition = (f32)(position-intPosition); //the position's fraction
- const f32 smpA = src[ intPosition ];
- const f32 smpB = src[(intPosition+1)%loopEnd];
- return LERP2(smpA, smpB, modPosition);
- }
- static inline Stereo_f32 linearSmpStereo(const Stereo_f32* src, f64 position,
- u64 loopEnd = KIT_U64_MAX)
- {
- const u64 intPosition = (u64)position;
- const f32 modPosition = (f32)(position-intPosition); //the position's fraction
- const Stereo_f32 smpA = src[ intPosition ];
- const Stereo_f32 smpB = src[(intPosition+1)%loopEnd];
- return Stereo_f32(LERP2(smpA.l, smpB.l, modPosition),
- LERP2(smpA.r, smpB.r, modPosition));
- }
- /******************************************************************************/
- static inline bool mixTrack(_SoundEngineTrack& track, u64 refTimestamp,
- bool sIVIZ, f32 sampleRate, Stereo_f32 volumeMaster,
- Stereo_f32* dst, size_t dst_len)
- {
- //the value volumeDelta is set to if the track hits 0x speed
- const Stereo_f32 speed0VDelta = -( (1000.0f/speed0VolDeltaMS) / sampleRate );
- //create stack copy of track data
- //(all but a track's deltas are to be referenced with this!)
- _SoundEngineTrack trk = track;
- if(trk.audio == nullptr){ //just in case
- SDL_SetError("track's audio = nullptr");
- return false;
- }
- //make copies of relevant data from trk.audio
- const bool stereo = trk.audio->channels==2;
- const u64 loopStart = trk.audio->loopStart;
- const u64 loopEnd = trk.audio->loopEnd; //(doubles as src_len)
- const f32* src_m = ( f32*)trk.audio->samples;
- const Stereo_f32* src_s = (Stereo_f32*)trk.audio->samples;
- u64 loopDifference = loopEnd - loopStart;
- //calculate position based on the difference between
- //the reference and the queued audio clip's timestamps
- if(trk.timestamp > 0){
- f64 difference = (f64)(((s64)refTimestamp)-((s64)trk.timestamp)); //ms
- difference /= 1000; //milliseconds -> seconds
- difference *= sampleRate; //seconds -> samples
- //(starts playing when position reaches 0)
- trk.position = -(difference*trk.spd_old);
- //(alternate calculation; try this if timing feels wrong or something)
- //trk.position = difference*trk.spd_old - dst_len;
- track.timestamp = 0; //to ensure that this only occurs once per clip queued
- }
- //used for interpolating speed and volume settings from old to new
- f32 t = 0.0f;
- const f32 t_inc = 1.0f/dst_len; //t_inc[rement]
- if(!stereo) //source is mono
- for(size_t i=0; i<dst_len; ++i){
- HANDLE_LOOP;
- //get sample
- f32 smp = linearSmpMono(src_m, trk.position, loopEnd);
- //apply volumes while interpolating between its old and new state
- smp *= volumeMaster.l * LERP2(trk.vol_old.l, trk.vol_new.l, t);
- //mix sample to dst (which is always stereo, so mix smp into both channels)
- dst[i].l += smp;
- dst[i].r += smp;
- //update position by speed, while interpolating between speed's old and new state
- trk.position += LERP2(trk.spd_old, trk.spd_new, t);
- //change old and new volume by volumeDelta
- //(deltas are referenced directly with track instead of trk)
- const f32 currentVolumeDelta = track.volDelta.l;
- trk.vol_old.l += currentVolumeDelta;
- trk.vol_new.l += currentVolumeDelta;
- //make sure both volumes are always between 0.0f and 1.0f
- trk.vol_old.l = CLAMP(trk.vol_old.l, 0.0f, 1.0f);
- trk.vol_new.l = CLAMP(trk.vol_new.l, 0.0f, 1.0f);
- HANDLE_SPEED_UPDATE
- }
- else //source is stereo
- for(size_t i=0; i<dst_len; ++i){
- HANDLE_LOOP;
- //get sample
- Stereo_f32 smp = linearSmpStereo(src_s, trk.position, loopEnd);
- //apply volumes while interpolating between its old and new state
- smp.l *= volumeMaster.l * LERP2(trk.vol_old.l, trk.vol_new.l, t);
- smp.r *= volumeMaster.r * LERP2(trk.vol_old.r, trk.vol_new.r, t);
- //mix sample to dst
- dst[i].l += smp.l;
- dst[i].r += smp.r;
- //update position by speed, while interpolating between speed's old and new state
- trk.position += LERP2(trk.spd_old, trk.spd_new, t);
- //change old and new volume by volumeDelta
- //(deltas are referenced directly with track instead of trk)
- const Stereo_f32 currentVolumeDelta = track.volDelta;
- trk.vol_old.l += currentVolumeDelta.l;
- trk.vol_old.r += currentVolumeDelta.r;
- trk.vol_new.l += currentVolumeDelta.l;
- trk.vol_new.r += currentVolumeDelta.r;
- //make sure both volumes are always between 0.0f and 1.0f
- trk.vol_old.l = CLAMP(trk.vol_old.l, 0.0f, 1.0f);
- trk.vol_old.r = CLAMP(trk.vol_old.r, 0.0f, 1.0f);
- trk.vol_new.l = CLAMP(trk.vol_new.l, 0.0f, 1.0f);
- trk.vol_new.r = CLAMP(trk.vol_new.r, 0.0f, 1.0f);
- HANDLE_SPEED_UPDATE
- }
- //set relevant old values to the new ones
- //(deltas don't need to be set)
- track.position = trk.position;
- track.spd_old = trk.spd_new; //both old *and* new speeds
- track.spd_new = trk.spd_new; //must be set to their new values
- track.vol_old = trk.vol_new; //both old *and* new volumes
- track.vol_new = trk.vol_new; //must be set to their new values
- track.loops = trk.loops;
- track.stopping = trk.stopping;
- //if stopIfVolumeIsZero while volume is <=0,
- //mark the track as stopping (if it wasn't already)
- //(sIVIZ is short for stopIfVolumeIsZero)
- if((!stereo && sIVIZ && trk.vol_new.l <= 0) ||
- ( stereo && sIVIZ && trk.vol_new.l <= 0 && trk.vol_new.r <= 0))
- {
- track.stopping = true;
- }
- //a track is marked as complete if either the clip finishes,
- //or if the volume goes at or below 0 while stopIfVolumeIsZero is true
- if(track.stopping) track.audio = nullptr;
- return true;
- }
- /******************************************************************************/
- //returns referenceTimestamp, or 0 on error
- u64 SoundEngine::mixTracks(Stereo_f32* buffer, size_t buffer_len,
- u64 referenceTimestamp)
- {
- if(MUTEX_PTR == nullptr){
- SDL_SetError("mutex = nullptr");
- return 0;
- }
- if(SDL_LockMutex(MUTEX_PTR)<0) return 0;
- if(_tracks == nullptr){
- SDL_SetError("_tracks = nullptr");
- referenceTimestamp = 0;
- _unlock_mutex_and_return:
- SDL_UnlockMutex(MUTEX_PTR);
- return referenceTimestamp;
- }
- //this will occur if you accidentally use the desired audio device's info
- //while sampleRate is set to 0 (which indicates that the default should
- //be used), instead of the audio device's actual sample rate.
- //this is because the desired info is a const that is not modified,
- //and thus keeping .sampleRate as 0 will set this to 0 as well.
- //TL;DR: use AudioDevice.info.sampleRate after construction instead
- //of using the AudioDeviceInfo you fed to the constructor
- if(sampleRate == 0.0f){
- SDL_SetError("sampleRate = 0.0f");
- return 0;
- }
- _SoundEngineTrack* tracks = _tracks;
- bool sIVIZ = stopIfVolumeIsZero;
- f32 smpRate = sampleRate;
- Stereo_f32 volMaster = volumeMaster;
- for(u16 t=0; t<_tracks_len; ++t){
- if(tracks[t].audio == nullptr) continue;
- //modify SoundEngine's master volume by the track's master volume
- Stereo_f32 _volMaster = volMaster;
- _volMaster.l *= tracks[t].volMaster.l;
- _volMaster.r *= tracks[t].volMaster.r;
- if(!mixTrack(tracks[t], referenceTimestamp, sIVIZ,
- smpRate, _volMaster, buffer, buffer_len))
- {
- return 0;
- }
- }
- goto _unlock_mutex_and_return;
- }
- }; /* namespace kit */
- /******************************************************************************/
- /******************************************************************************/
- //"2024-11-21\src\kit_sdl2\kit_Surface.cpp":
- #include "_kit_common.hpp"
- #define SURF_IS_INVALID (!_valid)
- #define SURF_PTR ((SDL_Surface*)_opq)
- namespace kit {
- Surface::Surface(u32 width, u32 height, u32 pixel_format){
- if(_valid) return;
- _type = KIT_CLASSTYPE_SURFACE;
- if(width > KIT_S32_MAX)
- THROW_ERROR("Surface::Surface(new): width > KIT_S32_MAX");
- if(height > KIT_S32_MAX)
- THROW_ERROR("Surface::Surface(new): height > KIT_S32_MAX");
- _opq = SDL_CreateRGBSurfaceWithFormat(0, width, height,
- SDL_BITSPERPIXEL(pixel_format),
- pixel_format);
- if(_opq == nullptr)
- THROW_ERRORF("Surface::Surface(new): \"%s\"", SDL_GetError());
- ++numAllocations;
- _valid = true;
- _constructing = false;
- }
- Surface::Surface(const Surface& src, u32 pixel_format){
- if(_valid) return;
- _type = KIT_CLASSTYPE_SURFACE;
- if(KIT_GET_CLASS_TYPE(&src) != KIT_CLASSTYPE_SURFACE)
- THROW_ERROR("Surface::Surface(Surface&): src is not a Surface class");
- SDL_Surface* src_surf = (SDL_Surface*)KIT_GET_CLASS_OPAQUE(&src);
- if(src_surf == nullptr)
- THROW_ERROR("Surface::Surface(Surface&): src._opq = nullptr");
- _opq = SDL_ConvertSurfaceFormat(src_surf, pixel_format, 0);
- if(_opq == nullptr)
- THROW_ERRORF("Surface::Surface(Surface&): \"%s\"", SDL_GetError());
- ++numAllocations;
- _valid = true;
- _constructing = false;
- }
- Surface::Surface(const Window& src, u32 pixel_format){
- if(_valid) return;
- _type = KIT_CLASSTYPE_SURFACE;
- if(KIT_GET_CLASS_TYPE(&src) != KIT_CLASSTYPE_WINDOW)
- THROW_ERROR("Surface::Surface(Window&): src is not a Window class");
- SDL_Window* src_win = (SDL_Window*)KIT_GET_CLASS_OPAQUE(&src);
- SDL_Surface** src_surf_p = (SDL_Surface**)&KIT_GET_CLASS_OPAQUE2(&src);
- bool src_surf_was_nullptr = *src_surf_p == nullptr;
- *src_surf_p = SDL_GetWindowSurface(src_win);
- if(*src_surf_p == nullptr){
- _throw_sdl_error:
- THROW_ERRORF("Surface::Surface(Window&): \"%s\"", SDL_GetError());
- }
- _opq = SDL_ConvertSurfaceFormat(*src_surf_p, pixel_format, 0);
- if(src_surf_was_nullptr){
- if(SDL_DestroyWindowSurface(src_win) < 0){
- if(_opq != nullptr){
- SDL_FreeSurface(SURF_PTR);
- _opq = nullptr;
- }
- goto _throw_sdl_error;
- }
- *src_surf_p = nullptr; //set back
- }
- if(_opq == nullptr) goto _throw_sdl_error;
- ++numAllocations;
- _valid = true;
- _constructing = false;
- }
- //does not increment numAllocations itself
- SDL_Surface* _invoke_surface_loader(const char* filePath,
- SurfaceLoaderCallback callback,
- const char* funcName)
- {
- if(!fileio::exists(filePath))
- THROW_ERRORF("%s: \"%s\" doesn't exist", funcName, filePath);
- SDL_Surface* surf;
- if(callback == nullptr){ //load .bmp file
- surf = SDL_LoadBMP(filePath);
- if(surf == nullptr) _sdl_err:
- THROW_ERRORF("%s: %s", funcName, SDL_GetError());
- } else { //load some other file format
- u32 format;
- u31 width, height;
- void* pixels_src = callback(filePath, format, width, height);
- if(pixels_src == nullptr)
- THROW_ERRORF("%s: callback() returned nullptr", funcName);
- surf = SDL_CreateRGBSurfaceWithFormat(0, width.n, height.n,
- SDL_BITSPERPIXEL(format), format);
- if(surf == nullptr){
- _free_src_and_sdl_err:
- memory::free(&pixels_src);
- goto _sdl_err;
- }
- if(SDL_LockSurface(surf) < 0)
- goto _free_src_and_sdl_err;
- void* pixels_dst = surf->pixels;
- s32 bytesPerRow = surf->pitch;
- //s32 height = surf->h;
- memory::copy(pixels_dst, pixels_src, bytesPerRow*height.n);
- SDL_UnlockSurface(surf);
- memory::free(&pixels_src);
- }
- return surf;
- }
- void Surface::_construct_file(const char* filePath,
- SurfaceLoaderCallback callback,
- const char* funcName)
- {
- if(_valid) return;
- _type = KIT_CLASSTYPE_SURFACE;
- if(funcName == nullptr)
- funcName = "Surface::Surface(specific file format)";
- if(filePath == nullptr)
- THROW_ERRORF("%s: filePath = nullptr", funcName);
- _opq = _invoke_surface_loader(filePath, callback, funcName);
- ++numAllocations;
- _valid = true;
- _constructing = false;
- }
- //(the last constructor can be found in "kit_Surface_LoadAllTypes.cpp")
- Surface::~Surface(){
- if(!_valid) return;
- _valid = false;
- if(SURF_PTR != nullptr){
- SDL_FreeSurface(SURF_PTR);
- _opq = nullptr;
- --numAllocations;
- }
- }
- //this is only used for saveImage, as this exists
- //as a byproduct of both SDL_LockSurface and the
- //SurfaceSaverCallback being able to error.
- //basically what this does is ensure that
- //SDL_UnlockSurface is called, even if the
- //SurfaceSaverCallback throws an exception
- struct _thing_that_locks_surface {
- SDL_Surface* ptr = nullptr;
- bool wasLocked = false;
- _thing_that_locks_surface(SDL_Surface* _ptr){
- if(SDL_LockSurface((ptr = _ptr)) < 0)
- THROW_ERRORF("Surface::saveImage(): \"%s\"", SDL_GetError());
- }
- ~_thing_that_locks_surface(){ SDL_UnlockSurface(ptr); }
- };
- void Surface::saveImage(const char* filePath, SurfaceSaverCallback callback){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::saveImage(): invalid Surface");
- if(filePath == nullptr)
- THROW_ERROR("Surface::saveImage(): filePath = nullptr");
- if(callback == nullptr){ //save .bmp file
- //afaik, you don't need to lock a surface before calling SDL_SaveBMP_RW,
- //(hopefully i'm not wrong about that!)
- if(SDL_SaveBMP(SURF_PTR, filePath) < 0)
- THROW_ERRORF("Surface::saveImage(): \"%s\"", SDL_GetError());
- } else { //save some other file format
- _thing_that_locks_surface surface_locker(SURF_PTR); //LMAOOO
- callback(filePath, *this);
- //(surface should unlock after this code block,
- //or if callback throws an exception)
- }
- }
- /******************************************************************************/
- bool Surface::hasRLE(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::hasRLE(): invalid Surface");
- return SDL_HasSurfaceRLE(SURF_PTR);
- }
- bool Surface::hasLockRequirement(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::hasRLE(): invalid Surface");
- return SDL_MUSTLOCK(SURF_PTR);
- }
- u32 Surface::getPixelFmt(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getPixelFmt(): invalid Surface");
- return SURF_PTR->format->format;
- }
- shape::point Surface::getSize(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getSize(): invalid Surface");
- return shape::point(SURF_PTR->w, SURF_PTR->h);
- }
- u32 Surface::getBytesPerRow(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getBytesPerRow(): invalid Surface");
- return (u32)SURF_PTR->pitch;
- }
- void* Surface::getPixelData(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getPixelData(): invalid Surface");
- return SURF_PTR->pixels;
- }
- void* Surface::getUserdata(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getUserdata(): invalid Surface");
- return SURF_PTR->userdata;
- }
- u32 Surface::getPaletteLen(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getPaletteLen(): invalid Surface");
- SDL_Palette* palette = SURF_PTR->format->palette;
- //idk if this is even possible, but just in case
- if(palette == nullptr) return 0;
- if(!SDL_ISPIXELFORMAT_INDEXED(SURF_PTR->format->format)) return 0;
- return (u32)palette->ncolors;
- }
- const colors::ABGR* Surface::getPaletteColors(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getPaletteColors(): invalid Surface");
- SDL_Palette* palette = SURF_PTR->format->palette;
- //idk if this is even possible, but just in case
- if(palette == nullptr) return nullptr;
- if(!SDL_ISPIXELFORMAT_INDEXED(SURF_PTR->format->format)) return nullptr;
- return (const colors::ABGR*)palette->colors;
- }
- BlendModesEnum Surface::getBlendMode(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getBlendMode(): invalid Surface");
- SDL_BlendMode blendMode;
- if(SDL_GetSurfaceBlendMode(SURF_PTR, &blendMode) < 0)
- THROW_ERRORF("Surface::getBlendMode(): \"%s\"", SDL_GetError());
- return (BlendModesEnum)blendMode;
- }
- u8 Surface::getAlphaMod(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getAlphaMod(): invalid Surface");
- u8 alphaMod;
- if(SDL_GetSurfaceAlphaMod(SURF_PTR, & alphaMod) < 0)
- THROW_ERRORF("Surface::getAlphaMod(): \"%s\"", SDL_GetError());
- return alphaMod;
- }
- colors::BGR Surface::getColorMod(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getColorMod(): invalid Surface");
- u8 r, g, b;
- if(SDL_GetSurfaceColorMod(SURF_PTR, &r, &g, &b) < 0)
- THROW_ERRORF("Surface::getColorMod(): \"%s\"", SDL_GetError());
- return colors::BGR888(r, g, b);
- }
- u32 Surface::getColorKey(){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::getColorKey(): invalid Surface");
- u32 key;
- if(SDL_GetColorKey(SURF_PTR, &key) < 0)
- THROW_ERRORF("Surface::getColorKey(): \"%s\"", SDL_GetError());
- return key;
- }
- /******************************************************************************/
- void Surface::setRLE(bool enable){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::setRLE(): invalid Surface");
- if(SDL_SetSurfaceRLE(SURF_PTR, enable) < 0)
- THROW_ERRORF("Surface::setRLE(): \"%s\"", SDL_GetError());
- }
- void Surface::setUserdata(void* userdata){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::setUserdata(): invalid Surface");
- SURF_PTR->userdata = userdata;
- }
- void Surface::setPaletteColors(const colors::ABGR* newColors,
- u32 numColors, u32 firstColor)
- {
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::setPaletteColors(): invalid Surface");
- if(newColors == nullptr)
- THROW_ERROR("Surface::setPaletteColors(): newColors = nullptr");
- if(numColors > KIT_S32_MAX)
- THROW_ERROR("Surface::setPaletteColors(): numColors > KIT_S32_MAX");
- if(firstColor > KIT_S32_MAX)
- THROW_ERROR("Surface::setPaletteColors(): firstColor > KIT_S32_MAX");
- SDL_Palette* palette = SURF_PTR->format->palette;
- if(!SDL_ISPIXELFORMAT_INDEXED(SURF_PTR->format->format) ||
- palette == nullptr || !palette->ncolors)
- {
- THROW_ERROR("Surface::setPaletteColors(): Surface doesn't use a palette");
- }
- if(SDL_SetPaletteColors(palette, (SDL_Color*)newColors, firstColor, numColors) < 0)
- THROW_ERRORF("Surface::setPaletteColors(): \"%s\"", SDL_GetError());
- }
- void Surface::setBlendMode(BlendModesEnum blendMode){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::setBlendMode(): invalid Surface");
- if(SDL_SetSurfaceBlendMode(SURF_PTR, (SDL_BlendMode)blendMode) < 0)
- THROW_ERRORF("Surface::setBlendMode(): \"%s\"", SDL_GetError());
- }
- void Surface::setAlphaMod(u8 alphaMod){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::setAlphaMod(): invalid Surface");
- if(SDL_SetSurfaceAlphaMod(SURF_PTR, alphaMod) < 0)
- THROW_ERRORF("Surface::setAlphaMod(): \"%s\"", SDL_GetError());
- }
- void Surface::setColorMod(colors::BGR colorMod){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::setColorMod(): invalid Surface");
- if(SDL_SetSurfaceColorMod(SURF_PTR, colorMod.r, colorMod.g, colorMod.b) < 0)
- THROW_ERRORF("Surface::setColorMod(): \"%s\"", SDL_GetError());
- }
- void Surface::setColorKey(bool enable, u32 key){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::setColorKey(): invalid Surface");
- if(SDL_SetColorKey(SURF_PTR, enable, key) < 0)
- THROW_ERRORF("Surface::setColorKey(): \"%s\"", SDL_GetError());
- }
- /******************************************************************************/
- u32 Surface::mapRGB(colors::BGR inputColor){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::mapRGB(): invalid Surface");
- return SDL_MapRGB(SURF_PTR->format, inputColor.r, inputColor.g, inputColor.b);
- }
- u32 Surface::mapRGBA(colors::ABGR inputColor){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::mapRGBA(): invalid Surface");
- return SDL_MapRGBA(SURF_PTR->format, inputColor.r, inputColor.g,
- inputColor.b, inputColor.a);
- }
- void Surface::lock(bool locked){
- if(SURF_IS_INVALID)
- THROW_ERROR("Surface::lock(): invalid Surface");
- if(locked){
- if(SDL_LockSurface(SURF_PTR) < 0)
- THROW_ERRORF("Surface::lock(): \"%s\"", SDL_GetError());
- } else {
- SDL_UnlockSurface(SURF_PTR);
- }
- }
- }; /* namespace kit */
- /******************************************************************************/
- /******************************************************************************/
- //"2024-11-21\src\kit_sdl2\kit_Surface_blit.cpp":
- #include "_kit_common.hpp"
- //i won't be checking for this here
- //(nor will i be doing most checks that i'd normally do)
- //#define SURF_IS_INVALID (!_valid)
- #define SURF_PTR ((SDL_Surface*)_opq)
- #define BLIT_SURF SDL_BlitSurface
- #define BLIT_SCALED SDL_BlitScaled
- namespace kit {
- void Surface::fillRects(colors::ABGR color, const shape::rect* rects,
- size_t rects_len)
- {
- if(rects_len > KIT_S32_MAX)
- THROW_ERROR("Surface::fillRects(): rects_len > KIT_S32_MAX");
- u32 mapped_color = SDL_MapRGBA(SURF_PTR->format, color.r, color.g,
- color.b, color.a);
- int err;
- if(rects == nullptr || !rects_len){
- err = SDL_FillRect(SURF_PTR, (SDL_Rect*)rects, mapped_color);
- } else {
- err = SDL_FillRects(SURF_PTR, (SDL_Rect*)rects, (int)rects_len, mapped_color);
- }
- if(err < 0)
- THROW_ERRORF("Surface::fillRects(): \"%s\"", SDL_GetError());
- }
- /******************************************************************************/
- void Surface::blit(Surface& dst_surf, const shape::rect* dst,
- const shape::rect* src)
- {
- SDL_Surface* dst_sdl = (SDL_Surface*)KIT_GET_CLASS_OPAQUE(&dst_surf);
- //(.w & .h of dst should be ignored by SDL_UpperBlit,
- //so setting them is unnecessary)
- SDL_Rect dstrect_sdl;
- SDL_Rect* dstrect_sdl_p;
- if(dst != nullptr){
- dstrect_sdl.x = dst->x;
- dstrect_sdl.y = dst->y;
- dstrect_sdl_p = &dstrect_sdl;
- } else {
- dstrect_sdl.x = 0;
- dstrect_sdl.y = 0;
- dstrect_sdl_p = nullptr;
- }
- if(BLIT_SURF(SURF_PTR, (SDL_Rect*)src, dst_sdl, dstrect_sdl_p) < 0)
- THROW_ERRORF("Surface::blit(Surface&): \"%s\"", SDL_GetError());
- }
- void Surface::blit(Window& dst_surf, const shape::rect* dst,
- const shape::rect* src)
- {
- SDL_Surface* dst_sdl = (SDL_Surface*)KIT_GET_CLASS_OPAQUE2(&dst_surf);
- if(dst_sdl == nullptr)
- THROW_ERROR("Surface::blit(Window&): Window doesn't have a surface");
- //(.w & .h of dst should be ignored by SDL_UpperBlit,
- //so setting them is unnecessary)
- SDL_Rect dstrect_sdl;
- SDL_Rect* dstrect_sdl_p;
- if(dst != nullptr){
- dstrect_sdl.x = dst->x;
- dstrect_sdl.y = dst->y;
- dstrect_sdl_p = &dstrect_sdl;
- } else {
- dstrect_sdl.x = 0;
- dstrect_sdl.y = 0;
- dstrect_sdl_p = nullptr;
- }
- if(BLIT_SURF(SURF_PTR, (SDL_Rect*)src, dst_sdl, dstrect_sdl_p) < 0)
- THROW_ERRORF("Surface::blit(Window&): \"%s\"", SDL_GetError());
- }
- /******************************************************************************/
- void Surface::blitScaled(Surface& dst_surf, const shape::rect* dst,
- const shape::rect* src)
- {
- SDL_Surface* dst_sdl = (SDL_Surface*)KIT_GET_CLASS_OPAQUE(&dst_surf);
- SDL_Rect dstrect_sdl;
- SDL_Rect* dstrect_sdl_p;
- if(dst != nullptr){
- dstrect_sdl = *(SDL_Rect*)dst;
- dstrect_sdl_p = &dstrect_sdl;
- } else {
- dstrect_sdl_p = nullptr;
- }
- if(BLIT_SCALED(SURF_PTR, (SDL_Rect*)src, dst_sdl, dstrect_sdl_p) < 0)
- THROW_ERRORF("Surface::blitScaled(Surface&): \"%s\"", SDL_GetError());
- }
- void Surface::blitScaled(Window& dst_surf, const shape::rect* dst,
- const shape::rect* src)
- {
- SDL_Surface* dst_sdl = (SDL_Surface*)KIT_GET_CLASS_OPAQUE2(&dst_surf);
- if(dst_sdl == nullptr)
- THROW_ERROR("Surface::blitScaled(Window&): Window doesn't have a surface");
- SDL_Rect dstrect_sdl;
- SDL_Rect* dstrect_sdl_p;
- if(dst != nullptr){
- dstrect_sdl = *(SDL_Rect*)dst;
- dstrect_sdl_p = &dstrect_sdl;
- } else {
- dstrect_sdl_p = nullptr;
- }
- if(BLIT_SCALED(SURF_PTR, (SDL_Rect*)src, dst_sdl, dstrect_sdl_p) < 0)
- THROW_ERRORF("Surface::blitScaled(Window&): \"%s\"", SDL_GetError());
- }
- /******************************************************************************/
- void Surface::blitAt(Surface& dst_surf, s32 x, s32 y, f32 scale){
- SDL_Surface* dst_sdl = (SDL_Surface*)KIT_GET_CLASS_OPAQUE(&dst_surf);
- SDL_Rect dstrect_sdl;
- dstrect_sdl.x = x;
- dstrect_sdl.y = y;
- dstrect_sdl.w = dst_sdl->w;
- dstrect_sdl.h = dst_sdl->h;
- int err;
- if(scale == 1.0f){ //fast blit
- dstrect_sdl.x -= dstrect_sdl.w/2;
- dstrect_sdl.y -= dstrect_sdl.h/2;
- err = BLIT_SURF(SURF_PTR, nullptr, dst_sdl, &dstrect_sdl);
- } else { //scaled blit
- dstrect_sdl.w *= scale;
- dstrect_sdl.h *= scale;
- dstrect_sdl.x -= dstrect_sdl.w/2;
- dstrect_sdl.y -= dstrect_sdl.h/2;
- err = BLIT_SCALED(SURF_PTR, nullptr, dst_sdl, &dstrect_sdl);
- }
- if(err) THROW_ERRORF("Surface::blitAt(Surface&): \"%s\"", SDL_GetError());
- }
- void Surface::blitAt(Window& dst_surf, s32 x, s32 y, f32 scale){
- SDL_Surface* dst_sdl = (SDL_Surface*)KIT_GET_CLASS_OPAQUE2(&dst_surf);
- if(dst_sdl == nullptr)
- THROW_ERROR("Surface::blitAt(Window&): Window doesn't have a surface");
- SDL_Rect dstrect_sdl;
- dstrect_sdl.x = x;
- dstrect_sdl.y = y;
- dstrect_sdl.w = dst_sdl->w;
- dstrect_sdl.h = dst_sdl->h;
- int err;
- if(scale == 1.0f){ //fast blit
- dstrect_sdl.x -= dstrect_sdl.w/2;
- dstrect_sdl.y -= dstrect_sdl.h/2;
- err = BLIT_SURF(SURF_PTR, nullptr, dst_sdl, &dstrect_sdl);
- } else { //scaled blit
- dstrect_sdl.w *= scale;
- dstrect_sdl.h *= scale;
- dstrect_sdl.x -= dstrect_sdl.w/2;
- dstrect_sdl.y -= dstrect_sdl.h/2;
- err = BLIT_SCALED(SURF_PTR, nullptr, dst_sdl, &dstrect_sdl);
- }
- if(err) THROW_ERRORF("Surface::blitAt(Window&): \"%s\"", SDL_GetError());
- }
- }; /* namespace kit */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement