<commit_before>/*
 * Copyright (c) 2007 SIEGE Development Team
 * All rights reserved.
 *
 * This file is part of libSIEGE.
 *
 * This software is copyrighted work licensed under the terms of the
 * 2-clause BSD license. Please consult the file "license.txt" for
 * details.
 *
 * If you did not recieve the file with this program, please email
 * <NAME> <<EMAIL>>.
 */

#define SG_BUILD_LIBRARY
#include <siege/core/window.h>
#include <siege/graphics/light.h>
#include <siege/graphics/draw.h>

#include <stdlib.h>
#include <math.h>

#define OP <=

/*
    TODO: change the way shadows are extended;
    currently, we use winw/winh, we should try getting some viewport info...
*/

static SGLightSpace* _sgLightGetSpace(void)
{
    if(!_sg_lightSpaceMain) _sg_lightSpaceMain = sgLightSpaceCreate();
    return _sg_lightSpaceMain;
}

SGbool SG_EXPORT _sgLightInit(void)
{
    _sg_lightSpaceMain = NULL;
    return SG_TRUE;
}
SGbool SG_EXPORT _sgLightDeinit(void)
{
    sgLightSpaceDestroy(_sg_lightSpaceMain);
    _sg_lightSpaceMain = NULL;

    return SG_TRUE;
}

void SG_EXPORT _sgLightSpaceAddLight(SGLightSpace* space, SGLight* light)
{
    if(space == NULL) space = _sgLightGetSpace();
    light->space = space;
    light->node = sgListAppend(space->lights, light);
}
void SG_EXPORT _sgLightSpaceAddShadowShape(SGLightSpace* space, SGShadowShape* shape)
{
    if(space == NULL) space = _sgLightGetSpace();
    shape->space = space;
    shape->node = sgListAppend(space->shapes, shape);
}
void SG_EXPORT _sgLightSpaceRemoveLight(SGLightSpace* space, SGLight* light)
{
    sgListRemoveNode(space->lights, light->node);
}
void SG_EXPORT _sgLightSpaceRemoveShadowShape(SGLightSpace* space, SGShadowShape* shape)
{
    sgListRemoveNode(space->shapes, shape->node);
}

SGLightSpace* SG_EXPORT sgLightSpaceCreate(void)
{
    SGLightSpace* space = malloc(sizeof(SGLightSpace));

    SGuint width, height;
    sgWindowGetSize(&width, &height);

    space->buffer = sgSurfaceCreate(width, height, 32);
    space->lbuffer = sgSurfaceCreate(width, height, 32);

    space->lights = sgListCreate();
    space->shapes = sgListCreate();

    space->ambience.r = 0.0;
    space->ambience.g = 0.0;
    space->ambience.b = 0.0;
    space->ambience.a = 0.0;

    return space;
}
void SG_EXPORT sgLightSpaceDestroy(SGLightSpace* space)
{
    if(!space)
        return;

    SGListNode* node;

    for(node = space->lights->head; node != NULL; node = node->next)
        sgLightDestroy(node->item);
    sgListDestroy(space->lights);

    for(node = space->shapes->head; node != NULL; node = node->next)
        sgShadowShapeDestroy(node->item);
    sgListDestroy(space->shapes);

    sgSurfaceDestroy(space->buffer);
    sgSurfaceDestroy(space->lbuffer);

    free(space);
}

void SG_EXPORT sgLightSpaceSetAmbience4f(SGLightSpace* space, float r, float g, float b, float a)
{
    space->ambience.r = r;
    space->ambience.g = g;
    space->ambience.b = b;
    space->ambience.a = a;
}

SGSurface* SG_EXPORT sgLightSpaceGetBuffer(SGLightSpace* space)
{
    return space->buffer;
}

void SG_EXPORT sgLightSpaceUpdate(SGLightSpace* space)
{
    SGListNode* lnode;
    SGListNode* snode;

    sgSurfaceClear4f(space->buffer, space->ambience.r, space->ambience.g, space->ambience.b, space->ambience.a);
    for(lnode = space->lights->head; lnode != NULL; lnode = lnode->next)
    {
        if(!sgLightGetActive(lnode->item))
            continue;
        sgDrawSetBlendFunc(SG_FUNC_ONE, SG_FUNC_ZERO);
        sgSurfaceClear4f(space->lbuffer, 0.0, 0.0, 0.0, 1.0);
        sgSurfaceTarget(space->lbuffer);
        sgLightDraw(lnode->item);
        if(sgLightGetShadow(lnode->item))
        {
            for(snode = space->shapes->head; snode != NULL; snode = snode->next)
            {
                if(!sgShadowShapeGetActive(snode->item))
                    continue;
                sgShadowShapeCast(snode->item, lnode->item);
            }
        }
        sgSurfaceUntarget(space->lbuffer);

        sgDrawSetBlendFunc(SG_FUNC_SRC_ALPHA, SG_FUNC_ONE);
        sgDrawColor4f(1.0, 1.0, 1.0, 1.0);
        sgSurfaceTarget(space->buffer);
        sgSurfaceDraw(space->lbuffer);
        sgSurfaceUntarget(space->buffer);
    }
    sgDrawSetBlendFunc(SG_FUNC_SRC_ALPHA, SG_FUNC_ONE_MINUS_SRC_ALPHA);
}
void SG_EXPORT sgLightSpaceDraw(SGLightSpace* space, SGenum flags)
{
    if(flags & SG_SHADOW_DRAW_MUL)
    {
        if(flags & SG_SHADOW_DRAW_SQR)
            sgDrawSetBlendFunc(SG_FUNC_DST_COLOR, SG_FUNC_SRC_COLOR);
        else
            sgDrawSetBlendFunc(SG_FUNC_DST_COLOR, SG_FUNC_ZERO);
    }
    else
        sgDrawSetBlendFunc(SG_FUNC_SRC_ALPHA, SG_FUNC_ONE);
    sgSurfaceDraw(space->buffer);
    sgDrawSetBlendFunc(SG_FUNC_SRC_ALPHA, SG_FUNC_ONE_MINUS_SRC_ALPHA);
}
void SG_EXPORT sgLightSpaceDrawDBG(SGLightSpace* space, SGenum flags)
{
    SGListNode* lnode;
    SGListNode* snode;
    for(snode = space->shapes->head; snode != NULL; snode = snode->next)
    {
        if(!sgShadowShapeGetActive(snode->item))
            continue;
        sgShadowShapeDrawDBG(snode->item, SG_TRUE);
    }
    for(snode = space->shapes->head; snode != NULL; snode = snode->next)
    {
        if(!sgShadowShapeGetActive(snode->item))
            continue;
        sgShadowShapeDrawDBG(snode->item, SG_FALSE);
    }
    for(lnode = space->lights->head; lnode != NULL; lnode = lnode->next)
    {<commit_msg>Made a note to myself about a certain blend mode in lights...<commit_after>/*
 * Copyright (c) 2007 SIEGE Development Team
 * All rights reserved.
 *
 * This file is part of libSIEGE.
 *
 * This software is copyrighted work licensed under the terms of the
 * 2-clause BSD license. Please consult the file "license.txt" for
 * details.
 *
 * If you did not recieve the file with this program, please email
 * <NAME> <<EMAIL>>.
 */

#define SG_BUILD_LIBRARY
#include <siege/core/window.h>
#include <siege/graphics/light.h>
#include <siege/graphics/draw.h>

#include <stdlib.h>
#include <math.h>

#define OP <=

/*
    TODO: change the way shadows are extended;
    currently, we use winw/winh, we should try getting some viewport info...
*/

static SGLightSpace* _sgLightGetSpace(void)
{
    if(!_sg_lightSpaceMain) _sg_lightSpaceMain = sgLightSpaceCreate();
    return _sg_lightSpaceMain;
}

SGbool SG_EXPORT _sgLightInit(void)
{
    _sg_lightSpaceMain = NULL;
    return SG_TRUE;
}
SGbool SG_EXPORT _sgLightDeinit(void)
{
    sgLightSpaceDestroy(_sg_lightSpaceMain);
    _sg_lightSpaceMain = NULL;

    return SG_TRUE;
}

void SG_EXPORT _sgLightSpaceAddLight(SGLightSpace* space, SGLight* light)
{
    if(space == NULL) space = _sgLightGetSpace();
    light->space = space;
    light->node = sgListAppend(space->lights, light);
}
void SG_EXPORT _sgLightSpaceAddShadowShape(SGLightSpace* space, SGShadowShape* shape)
{
    if(space == NULL) space = _sgLightGetSpace();
    shape->space = space;
    shape->node = sgListAppend(space->shapes, shape);
}
void SG_EXPORT _sgLightSpaceRemoveLight(SGLightSpace* space, SGLight* light)
{
    sgListRemoveNode(space->lights, light->node);
}
void SG_EXPORT _sgLightSpaceRemoveShadowShape(SGLightSpace* space, SGShadowShape* shape)
{
    sgListRemoveNode(space->shapes, shape->node);
}

SGLightSpace* SG_EXPORT sgLightSpaceCreate(void)
{
    SGLightSpace* space = malloc(sizeof(SGLightSpace));

    SGuint width, height;
    sgWindowGetSize(&width, &height);

    space->buffer = sgSurfaceCreate(width, height, 32);
    space->lbuffer = sgSurfaceCreate(width, height, 32);

    space->lights = sgListCreate();
    space->shapes = sgListCreate();

    space->ambience.r = 0.0;
    space->ambience.g = 0.0;
    space->ambience.b = 0.0;
    space->ambience.a = 0.0;

    return space;
}
void SG_EXPORT sgLightSpaceDestroy(SGLightSpace* space)
{
    if(!space)
        return;

    SGListNode* node;

    for(node = space->lights->head; node != NULL; node = node->next)
        sgLightDestroy(node->item);
    sgListDestroy(space->lights);

    for(node = space->shapes->head; node != NULL; node = node->next)
        sgShadowShapeDestroy(node->item);
    sgListDestroy(space->shapes);

    sgSurfaceDestroy(space->buffer);
    sgSurfaceDestroy(space->lbuffer);

    free(space);
}

void SG_EXPORT sgLightSpaceSetAmbience4f(SGLightSpace* space, float r, float g, float b, float a)
{
    space->ambience.r = r;
    space->ambience.g = g;
    space->ambience.b = b;
    space->ambience.a = a;
}

SGSurface* SG_EXPORT sgLightSpaceGetBuffer(SGLightSpace* space)
{
    return space->buffer;
}

void SG_EXPORT sgLightSpaceUpdate(SGLightSpace* space)
{
    SGListNode* lnode;
    SGListNode* snode;

    sgSurfaceClear4f(space->buffer, space->ambience.r, space->ambience.g, space->ambience.b, space->ambience.a);
    for(lnode = space->lights->head; lnode != NULL; lnode = lnode->next)
    {
        if(!sgLightGetActive(lnode->item))
            continue;
        sgDrawSetBlendFunc(SG_FUNC_ONE, SG_FUNC_ZERO);
        sgSurfaceClear4f(space->lbuffer, 0.0, 0.0, 0.0, 1.0);
        sgSurfaceTarget(space->lbuffer);
        sgLightDraw(lnode->item);
        if(sgLightGetShadow(lnode->item))
        {
            for(snode = space->shapes->head; snode != NULL; snode = snode->next)
            {
                if(!sgShadowShapeGetActive(snode->item))
                    continue;
                sgShadowShapeCast(snode->item, lnode->item);
            }
        }
        sgSurfaceUntarget(space->lbuffer);

        sgDrawSetBlendFunc(SG_FUNC_SRC_ALPHA, SG_FUNC_ONE);
        sgDrawColor4f(1.0, 1.0, 1.0, 1.0);
        sgSurfaceTarget(space->buffer);
        sgSurfaceDraw(space->lbuffer);
        sgSurfaceUntarget(space->buffer);
    }
    sgDrawSetBlendFunc(SG_FUNC_SRC_ALPHA, SG_FUNC_ONE_MINUS_SRC_ALPHA);
}
void SG_EXPORT sgLightSpaceDraw(SGLightSpace* space, SGenum flags)
{
    if(flags & SG_SHADOW_DRAW_MUL)
    {
        if(flags & SG_SHADOW_DRAW_SQR)
            sgDrawSetBlendFunc(SG_FUNC_DST_COLOR, SG_FUNC_SRC_COLOR);
        else
            sgDrawSetBlendFunc(SG_FUNC_DST_COLOR, SG_FUNC_ZERO);
    }
    else /* note to self: sgDrawSetBlendFunc(SG_FUNC_SRC_COLOR, SG_FUNC_ONE); makes for an interesting effect; I should prooly add an API for that */
        sgDrawSetBlendFunc(SG_FUNC_SRC_ALPHA, SG_FUNC_ONE);
    sgSurfaceDraw(space->buffer);
    sgDrawSetBlendFunc(SG_FUNC_SRC_ALPHA, SG_FUNC_ONE_MINUS_SRC_ALPHA);
}
void SG_EXPORT sgLightSpaceDrawDBG(SGLightSpace* space, SGenum flags)
{
    SGListNode* lnode;
    SGListNode* snode;
    for(snode = space->shapes->head; snode != NULL; snode = snode->next)
    {
        if(!sgShadowShapeGetActive(snode->item))
            continue;
        sgShadowShapeDrawDBG(snode->item, SG_TRUE);
    }
    for(snode = space->shapes->head; snode != NULL; snode = snode->next)
    {
        if(!sgShadowShapeGetActive(snode->item))
            continue;
        sgShadowShapeDrawDBG(snode->item, SG_FALSE);
    }
    for(lnode = space->lights->head; lnode != NULL; lnode = lnode->next)
    {
{'fraction_non_alphanumeric': 0.12065663474692202, 'fraction_numerical': 0.00674874601003192, 'mean_word_length': 3.459536396909313, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 163, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '785115', 'n_tokens_mistral': 4028, 'n_tokens_neox': 3742, 'n_words': 725}