This commit is contained in:
John Alanbrook 2023-05-12 18:22:05 +00:00
parent eb3e576521
commit e0f3985b00
84 changed files with 49281 additions and 19388 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
#ifndef TWODPHYSICS_H #ifndef TWODPHYSICS_H
#define TWODPHYSICS_H #define TWODPHYSICS_H
#include <chipmunk/chipmunk.h>
#include "script.h" #include "script.h"
#include <chipmunk/chipmunk.h>
struct gameobject; struct gameobject;
@ -18,53 +18,53 @@ extern float kinematic_color[3];
extern float static_color[3]; extern float static_color[3];
struct phys2d_shape { struct phys2d_shape {
cpShape *shape; cpShape *shape;
int go; int go;
void *data; void *data;
void (*debugdraw)(void *data); void (*debugdraw)(void *data);
float (*moi)(void *data, float mass); float (*moi)(void *data, float mass);
}; };
/* Circles are the fastest collier type */ /* Circles are the fastest collier type */
struct phys2d_circle { struct phys2d_circle {
float radius; float radius;
cpVect offset; cpVect offset;
struct phys2d_shape shape; struct phys2d_shape shape;
}; };
/* A single segment */ /* A single segment */
struct phys2d_segment { struct phys2d_segment {
float a[2]; float a[2];
float b[2]; float b[2];
float thickness; float thickness;
struct phys2d_shape shape; struct phys2d_shape shape;
}; };
/* A convex polygon; defined as the convex hull around the given set of points */ /* A convex polygon; defined as the convex hull around the given set of points */
struct phys2d_poly { struct phys2d_poly {
cpVect *points; cpVect *points;
float radius; float radius;
struct phys2d_shape shape; struct phys2d_shape shape;
}; };
/* A box shape; a type of a polygon collider */ /* A box shape; a type of a polygon collider */
struct phys2d_box { struct phys2d_box {
float w; float w;
float h; float h;
float offset[2]; float offset[2];
float rotation; float rotation;
float r; float r;
struct phys2d_shape shape; struct phys2d_shape shape;
}; };
/* An edge with no volume. Cannot collide with each other. Join to make levels. Static only. */ /* An edge with no volume. Cannot collide with each other. Join to make levels. Static only. */
struct phys2d_edge { struct phys2d_edge {
cpVect *points; cpVect *points;
float thickness; float thickness;
cpShape **shapes; cpShape **shapes;
int closed; /* True if the first and last points should be connected */ int closed; /* True if the first and last points should be connected */
struct phys2d_shape shape; struct phys2d_shape shape;
int draws; int draws;
}; };
struct phys2d_circle *Make2DCircle(int go); struct phys2d_circle *Make2DCircle(int go);
@ -107,8 +107,8 @@ cpShape *phys2d_query_pos(cpVect pos);
int *phys2d_query_box(cpVect pos, cpVect wh); int *phys2d_query_box(cpVect pos, cpVect wh);
struct phys_cbs { struct phys_cbs {
struct callee begin; struct callee begin;
struct callee separate; struct callee separate;
}; };
struct shape_cb { struct shape_cb {
@ -127,9 +127,9 @@ void shape_set_sensor(struct phys2d_shape *shape, int sensor);
int shape_get_sensor(struct phys2d_shape *shape); int shape_get_sensor(struct phys2d_shape *shape);
struct color { struct color {
unsigned char r; unsigned char r;
unsigned char g; unsigned char g;
unsigned char b; unsigned char b;
}; };
void color2float(struct color, float *fcolor); void color2float(struct color, float *fcolor);

View file

@ -1,5 +1,4 @@
#ifndef THREEDPHYSICS_H #ifndef THREEDPHYSICS_H
#define THREEDPHYSICS_H #define THREEDPHYSICS_H
#endif #endif

View file

@ -42,26 +42,26 @@ glm::vec3 ThirdPersonFollow::CalculatePosition()
glm::vec3 p1 = CalculateCenter(); glm::vec3 p1 = CalculateCenter();
glm::vec3 p2 = glm::vec3 p2 =
XDirPosts ? GetPostsOffset(TFOR.Right(), XDirPosts ? GetPostsOffset(TFOR.Right(),
FloatWidths. FloatWidths.
x) : GetExtentsOffset(TFOR.Right(), x) : GetExtentsOffset(TFOR.Right(),
FloatWidths.x, FloatWidths.x,
TargetOffset.x, TargetOffset.x,
AnchorWidths.x); AnchorWidths.x);
glm::vec3 p3 = glm::vec3 p3 =
YDirPosts ? GetPostsOffset(TFOR.Up(), YDirPosts ? GetPostsOffset(TFOR.Up(),
FloatWidths. FloatWidths.
y) : GetExtentsOffset(TFOR.Up(), y) : GetExtentsOffset(TFOR.Up(),
FloatWidths.y, FloatWidths.y,
TargetOffset.y, TargetOffset.y,
AnchorWidths.y); AnchorWidths.y);
glm::vec3 p4 = glm::vec3 p4 =
ZDirPosts ? GetPostsOffset(TFOR.Back(), ZDirPosts ? GetPostsOffset(TFOR.Back(),
FloatWidths. FloatWidths.
z) : GetExtentsOffset(TFOR.Back(), z) : GetExtentsOffset(TFOR.Back(),
FloatWidths.z, FloatWidths.z,
TargetOffset.z, TargetOffset.z,
AnchorWidths.z); AnchorWidths.z);
return p1 + p2 + p3 + p4; return p1 + p2 + p3 + p4;
} }
@ -69,7 +69,7 @@ glm::vec3 ThirdPersonFollow::CalculatePosition()
glm::vec3 ThirdPersonFollow::CalculateCenter() glm::vec3 ThirdPersonFollow::CalculateCenter()
{ {
return Target->get_global_translation() + return Target->get_global_translation() +
TFOR.TransformDirection(Offset) + (mytransform->Back() * Distance); TFOR.TransformDirection(Offset) + (mytransform->Back() * Distance);
} }
glm::vec3 ThirdPersonFollow:: glm::vec3 ThirdPersonFollow::
@ -82,37 +82,37 @@ GetPostsOffset(const glm::vec3 & DirectionVector, float AnchorWidth)
glm::vec3 ThirdPersonFollow:: glm::vec3 ThirdPersonFollow::
GetExtentsOffset(const glm::vec3 & DirectionVector, float AnchorWidth, GetExtentsOffset(const glm::vec3 & DirectionVector, float AnchorWidth,
float TOffset, float Width) float TOffset, float Width)
{ {
float negated_offset_sign = ((0 <= TOffset) - (TOffset < 0)) * -1.f; float negated_offset_sign = ((0 <= TOffset) - (TOffset < 0)) * -1.f;
float TotalWidth = AnchorWidth + Width; float TotalWidth = AnchorWidth + Width;
if (glm::abs(TOffset) > TotalWidth if (glm::abs(TOffset) > TotalWidth
&& !glm::epsilonEqual(glm::abs(TOffset), TotalWidth, 0.5f)) && !glm::epsilonEqual(glm::abs(TOffset), TotalWidth, 0.5f))
return DirectionVector * TotalWidth * negated_offset_sign; return DirectionVector * TotalWidth * negated_offset_sign;
else { else {
if (glm::abs(TOffset) >= AnchorWidth) if (glm::abs(TOffset) >= AnchorWidth)
return DirectionVector * AnchorWidth * negated_offset_sign; return DirectionVector * AnchorWidth * negated_offset_sign;
else else
return DirectionVector * TOffset * -1.f; return DirectionVector * TOffset * -1.f;
} }
return glm::vec3(0.f); return glm::vec3(0.f);
} }
glm::vec3 ThirdPersonFollow::FrameBasedVectorLerp(const glm::vec3 & From, glm::vec3 ThirdPersonFollow::FrameBasedVectorLerp(const glm::vec3 & From,
const glm::vec3 & To, const glm::vec3 & To,
const glm::vec3 & Speeds, const glm::vec3 & Speeds,
float Tick) float Tick)
{ {
// Previously "FORTransform.TransformVector(Speeds) // Previously "FORTransform.TransformVector(Speeds)
glm::vec3 TSpeed = glm::abs(TFOR.TransformDirection(Speeds)); glm::vec3 TSpeed = glm::abs(TFOR.TransformDirection(Speeds));
glm::vec3 TOffset = glm::abs(TFOR.TransformDirection(TargetOffset)); glm::vec3 TOffset = glm::abs(TFOR.TransformDirection(TargetOffset));
glm::vec3 TAnchorWidths = glm::vec3 TAnchorWidths =
glm::abs(TFOR.TransformDirection(AnchorWidths)); glm::abs(TFOR.TransformDirection(AnchorWidths));
glm::vec3 TFloatWidths = glm::vec3 TFloatWidths =
glm::abs(TFOR.TransformDirection(FloatWidths)); glm::abs(TFOR.TransformDirection(FloatWidths));
@ -124,14 +124,14 @@ glm::vec3 ThirdPersonFollow::FrameBasedVectorLerp(const glm::vec3 & From,
float xAlpha = float xAlpha =
glm::clamp((bUseX ? AnchorSpeed : TSpeed.x) * Tick, 0.f, 1.f); glm::clamp((bUseX ? AnchorSpeed : TSpeed.x) * Tick, 0.f, 1.f);
float yAlpha = float yAlpha =
glm::clamp((bUseY ? AnchorSpeed : TSpeed.y) * Tick, 0.f, 1.f); glm::clamp((bUseY ? AnchorSpeed : TSpeed.y) * Tick, 0.f, 1.f);
float zAlpha = float zAlpha =
glm::clamp((bUseZ ? AnchorSpeed : TSpeed.z) * Tick, 0.f, 1.f); glm::clamp((bUseZ ? AnchorSpeed : TSpeed.z) * Tick, 0.f, 1.f);
return VectorLerpPiecewise(From, To, return VectorLerpPiecewise(From, To,
glm::vec3(xAlpha, yAlpha, zAlpha)); glm::vec3(xAlpha, yAlpha, zAlpha));
} }
int float_epsilon(mfloat_t a, mfloat_t b, mfloat_t e) int float_epsilon(mfloat_t a, mfloat_t b, mfloat_t e)
@ -165,11 +165,11 @@ void ThirdPersonFollow::CalculateTargets()
// For rotation // For rotation
// TODO: Check of this implementation is the same as UKismetMath FindLookAtRotation // TODO: Check of this implementation is the same as UKismetMath FindLookAtRotation
TargetRotation = TargetRotation =
RemoveLockedRotation(glm::quat RemoveLockedRotation(glm::quat
(mytransform-> (mytransform->
get_global_transform()->get_origin() - get_global_transform()->get_origin() -
Target-> Target->
get_global_transform()->get_origin())); get_global_transform()->get_origin()));
} }
follow_removelockedrot() follow_removelockedrot()
@ -185,11 +185,11 @@ RemoveLockedRotation(const glm::quat & CurrentRotation)
// //
NewRotator.x = NewRotator.x =
LockRoll ? mytransform->get_rotation().x : CurrentRotator.x; LockRoll ? mytransform->get_rotation().x : CurrentRotator.x;
NewRotator.y = NewRotator.y =
LockPitch ? mytransform->get_rotation().y : CurrentRotator.y; LockPitch ? mytransform->get_rotation().y : CurrentRotator.y;
NewRotator.z = NewRotator.z =
LockYaw ? mytransform->get_rotation().z : CurrentRotator.z; LockYaw ? mytransform->get_rotation().z : CurrentRotator.z;
return glm::quat(NewRotator); return glm::quat(NewRotator);
} }
@ -199,11 +199,11 @@ RemoveLockedRotation(const glm::quat & CurrentRotation)
void ThirdPersonFollow::CalculateTargetOffset() void ThirdPersonFollow::CalculateTargetOffset()
{ {
glm::vec3 p1 = glm::vec3 p1 =
(mytransform->Forward() * Distance) + (mytransform->Forward() * Distance) +
TFOR.TransformDirection(Offset) + TFOR.TransformDirection(Offset) +
mytransform->get_global_translation(); mytransform->get_global_translation();
glm::vec3 p2 = glm::vec3 p2 =
TFOR.InverseTransformDirection(Target->get_global_translation()); TFOR.InverseTransformDirection(Target->get_global_translation());
glm::vec3 p3 = TFOR.InverseTransformDirection(p1); glm::vec3 p3 = TFOR.InverseTransformDirection(p1);
TargetOffset = p2 - p3; TargetOffset = p2 - p3;

View file

@ -6,8 +6,8 @@
#include "transform.h" #include "transform.h"
struct follow { struct follow {
float distance; float distance;
mfloat_t target_rot[4]; mfloat_t target_rot[4];
}; };
mfloat_t *follow_calccenter(); mfloat_t *follow_calccenter();
@ -31,45 +31,45 @@ class ThirdPersonFollow {
public: public:
enum CameraType { enum CameraType {
STATIONARY, STATIONARY,
TRANSLATING, TRANSLATING,
ROTATING, ROTATING,
SPLINE SPLINE
}; };
enum CameraTransition { enum CameraTransition {
NONE, NONE,
CROSSDISSOLVE, CROSSDISSOLVE,
WIPE, WIPE,
DIP DIP
}; };
enum FrameOfReference { enum FrameOfReference {
LOCAL, LOCAL,
WORLD, WORLD,
EXTERNAL EXTERNAL
}; };
ThirdPersonFollow() { ThirdPersonFollow() {
// Rotation // Rotation
RotationSpeed = 10.0f; RotationSpeed = 10.0f;
LockPitch = LockYaw = LockRoll = true; LockPitch = LockYaw = LockRoll = true;
XDirPosts = false; XDirPosts = false;
YDirPosts = false; YDirPosts = false;
ZDirPosts = false; ZDirPosts = false;
// Translation // Translation
//FloatWidths = AnchorWidths = CenterVector = glm::vec3(0, 0, 0); //FloatWidths = AnchorWidths = CenterVector = glm::vec3(0, 0, 0);
PositionSpeeds = glm::vec3(2.f, 2.f, 2.f); PositionSpeeds = glm::vec3(2.f, 2.f, 2.f);
//TranslationScales = glm::vec3(1, 1, 1); //TranslationScales = glm::vec3(1, 1, 1);
// Frame settings // Frame settings
Offset = glm::vec3(0.f, 0.f, 0.f); Offset = glm::vec3(0.f, 0.f, 0.f);
Distance = 10; Distance = 10;
AnchorSpeed = 80; AnchorSpeed = 80;
} ~ThirdPersonFollow() { } ~ThirdPersonFollow() {
} }
@ -81,14 +81,14 @@ class ThirdPersonFollow {
void SetExternalFrame(Transform * val) { void SetExternalFrame(Transform * val) {
ExternalFrame = val; ExternalFrame = val;
} }
// The target the camera "looks" at, used for calculations // The target the camera "looks" at, used for calculations
Transform *Target = nullptr; Transform *Target = nullptr;
void SetTarget(Transform * val) { void SetTarget(Transform * val) {
Target = val; Target = val;
} }
// Offset from the target // Offset from the target
@ -158,25 +158,25 @@ class ThirdPersonFollow {
/// Given a direction and width, find the offsets. /// Given a direction and width, find the offsets.
glm::vec3 GetPostsOffset(const glm::vec3 & DirectionVector, glm::vec3 GetPostsOffset(const glm::vec3 & DirectionVector,
float AnchorWidth); float AnchorWidth);
/// Given anchors, what's the anchor width? /// Given anchors, what's the anchor width?
glm::vec3 GetExtentsOffset(const glm::vec3 & DirectionVector, glm::vec3 GetExtentsOffset(const glm::vec3 & DirectionVector,
float AnchorWidth, float TOffset, float AnchorWidth, float TOffset,
float Width); float Width);
glm::quat RemoveLockedRotation(const glm::quat & CurrentRotation); glm::quat RemoveLockedRotation(const glm::quat & CurrentRotation);
glm::vec3 FrameBasedVectorLerp(const glm::vec3 & From, glm::vec3 FrameBasedVectorLerp(const glm::vec3 & From,
const glm::vec3 & To, const glm::vec3 & To,
const glm::vec3 & Speeds, float Tick); const glm::vec3 & Speeds, float Tick);
glm::vec3 VectorLerpPiecewise(const glm::vec3 & From, glm::vec3 VectorLerpPiecewise(const glm::vec3 & From,
const glm::vec3 & To, const glm::vec3 & To,
const glm::vec3 & Alpha); const glm::vec3 & Alpha);
bool GetLerpParam(const float Offst, const float AnchorWidth, bool GetLerpParam(const float Offst, const float AnchorWidth,
const float FloatWidth); const float FloatWidth);
/// Set to a value that gives good clamping, smoothly. Activates when /// Set to a value that gives good clamping, smoothly. Activates when
/// the target is out of range. /// the target is out of range.

View file

@ -1,7 +1,6 @@
#include "light.h" #include "light.h"
#include <stdbool.h> #include <stdbool.h>
/* /*
void Light::serialize(FILE * file) void Light::serialize(FILE * file)
{ {
@ -30,20 +29,20 @@ struct mDirectionalLight *dLight = NULL;
struct mDirectionalLight *MakeDLight() struct mDirectionalLight *MakeDLight()
{ {
if (dLight != NULL) { if (dLight != NULL) {
dLight = dLight =
(struct mDirectionalLight *) (struct mDirectionalLight *)
malloc(sizeof(struct mDirectionalLight)); malloc(sizeof(struct mDirectionalLight));
quat_from_euler(dLight->light.obj.transform.rotation, quat_from_euler(dLight->light.obj.transform.rotation,
dlight_init_rot); dlight_init_rot);
return dLight; return dLight;
} }
return dLight; return dLight;
} }
void dlight_prepshader(struct mDirectionalLight *light, void dlight_prepshader(struct mDirectionalLight *light,
struct shader *shader) struct shader *shader)
{ {
mfloat_t fwd[3] = { 0.f }; mfloat_t fwd[3] = { 0.f };
trans_forward(fwd, &light->light.obj.transform); trans_forward(fwd, &light->light.obj.transform);
@ -61,14 +60,14 @@ static int numLights = 0;
struct mPointLight *MakePointlight() struct mPointLight *MakePointlight()
{ {
if (numLights < 4) { if (numLights < 4) {
struct mPointLight *light = struct mPointLight *light =
(struct mPointLight *) malloc(sizeof(struct mPointLight)); (struct mPointLight *) malloc(sizeof(struct mPointLight));
pointLights[numLights++] = light; pointLights[numLights++] = light;
light->light.strength = 0.2f; light->light.strength = 0.2f;
light->constant = 1.f; light->constant = 1.f;
light->linear = 0.9f; light->linear = 0.9f;
light->quadratic = 0.032f; light->quadratic = 0.032f;
return light; return light;
} }
return NULL; return NULL;
@ -82,11 +81,11 @@ static void prepstring(char *buffer, char *prepend, const char *append)
void pointlights_prepshader(struct shader *shader) void pointlights_prepshader(struct shader *shader)
{ {
for (int i = 0; i < numLights; i++) for (int i = 0; i < numLights; i++)
pointlight_prepshader(pointLights[i], shader, i); pointlight_prepshader(pointLights[i], shader, i);
} }
void pointlight_prepshader(struct mPointLight *light, void pointlight_prepshader(struct mPointLight *light,
struct shader *shader, int num) struct shader *shader, int num)
{ {
shader_use(shader); shader_use(shader);
char prepend[100] = { '\0' }; char prepend[100] = { '\0' };
@ -121,10 +120,10 @@ static int numSpots = 0;
struct mSpotLight *MakeSpotlight() struct mSpotLight *MakeSpotlight()
{ {
if (numSpots < 4) { if (numSpots < 4) {
struct mSpotLight *light = struct mSpotLight *light =
(struct mSpotLight *) malloc(sizeof(struct mSpotLight)); (struct mSpotLight *) malloc(sizeof(struct mSpotLight));
spotLights[numSpots++] = light; spotLights[numSpots++] = light;
return light; return light;
} }
return NULL; return NULL;
@ -135,17 +134,17 @@ struct mSpotLight *MakeSpotlight()
void spotlights_prepshader(struct shader *shader) void spotlights_prepshader(struct shader *shader)
{ {
for (int i = 0; i < numSpots; i++) for (int i = 0; i < numSpots; i++)
spotlight_prepshader(spotLights[i], shader, i); spotlight_prepshader(spotLights[i], shader, i);
} }
void spotlight_prepshader(struct mSpotLight *light, struct shader *shader, void spotlight_prepshader(struct mSpotLight *light, struct shader *shader,
int num) int num)
{ {
mfloat_t fwd[3] = { 0.f }; mfloat_t fwd[3] = { 0.f };
trans_forward(fwd, &light->light.obj.transform); trans_forward(fwd, &light->light.obj.transform);
shader_use(shader); shader_use(shader);
shader_setvec3(shader, "spotLight.position", shader_setvec3(shader, "spotLight.position",
light->light.obj.transform.position); light->light.obj.transform.position);
shader_setvec3(shader, "spotLight.direction", fwd); shader_setvec3(shader, "spotLight.direction", fwd);
shader_setvec3(shader, "spotLight.color", light->light.color); shader_setvec3(shader, "spotLight.color", light->light.color);
shader_setfloat(shader, "spotLight.strength", light->light.strength); shader_setfloat(shader, "spotLight.strength", light->light.strength);
@ -165,10 +164,10 @@ void light_gui(struct mLight *light)
object_gui(&light->obj); object_gui(&light->obj);
if (nk_tree_push(ctx, NK_TREE_NODE, "Light", NK_MINIMIZED)) { if (nk_tree_push(ctx, NK_TREE_NODE, "Light", NK_MINIMIZED)) {
nk_property_float(ctx, "Strength", 0.f, &light->strength, 1.f, 0.01f, 0.001f); nk_property_float(ctx, "Strength", 0.f, &light->strength, 1.f, 0.01f, 0.001f);
// ImGui::ColorEdit3("Color", &light->color[0]); // ImGui::ColorEdit3("Color", &light->color[0]);
nk_checkbox_label(ctx, "Dynamic", (bool *) &light->dynamic); nk_checkbox_label(ctx, "Dynamic", (bool *) &light->dynamic);
nk_tree_pop(ctx); nk_tree_pop(ctx);
} }
} }
@ -178,10 +177,10 @@ void pointlight_gui(struct mPointLight *light)
light_gui(&light->light); light_gui(&light->light);
if (nk_tree_push(ctx, NK_TREE_NODE, "Point Light", NK_MINIMIZED)) { if (nk_tree_push(ctx, NK_TREE_NODE, "Point Light", NK_MINIMIZED)) {
nk_property_float(ctx, "Constant", 0.f, &light->constant, 1.f, 0.01f, 0.001f); nk_property_float(ctx, "Constant", 0.f, &light->constant, 1.f, 0.01f, 0.001f);
nk_property_float(ctx, "Linear", 0.f, &light->linear, 0.3f, 0.01f, 0.001f); nk_property_float(ctx, "Linear", 0.f, &light->linear, 0.3f, 0.01f, 0.001f);
nk_property_float(ctx, "Quadratic", 0.f, &light->quadratic, 0.3f, 0.01f, 0.001f); nk_property_float(ctx, "Quadratic", 0.f, &light->quadratic, 0.3f, 0.01f, 0.001f);
nk_tree_pop(ctx); nk_tree_pop(ctx);
} }
} }
@ -191,12 +190,12 @@ void spotlight_gui(struct mSpotLight *spot)
light_gui(&spot->light); light_gui(&spot->light);
if (nk_tree_push(ctx, NK_TREE_NODE, "Spotlight", NK_MINIMIZED)) { if (nk_tree_push(ctx, NK_TREE_NODE, "Spotlight", NK_MINIMIZED)) {
nk_property_float(ctx, "Linear", 0.f, &spot->linear, 1.f, 0.01f, 0.001f); nk_property_float(ctx, "Linear", 0.f, &spot->linear, 1.f, 0.01f, 0.001f);
nk_property_float(ctx, "Quadratic", 0.f, &spot->quadratic, 1.f, 0.01f, 0.001f); nk_property_float(ctx, "Quadratic", 0.f, &spot->quadratic, 1.f, 0.01f, 0.001f);
nk_property_float(ctx, "Distance", 0.f, &spot->distance, 200.f, 1.f, 0.1f, 200.f); nk_property_float(ctx, "Distance", 0.f, &spot->distance, 200.f, 1.f, 0.1f, 200.f);
nk_property_float(ctx, "Cutoff Degrees", 0.f, &spot->cutoff, 0.7f, 0.01f, 0.001f); nk_property_float(ctx, "Cutoff Degrees", 0.f, &spot->cutoff, 0.7f, 0.01f, 0.001f);
nk_property_float(ctx, "Outer Cutoff Degrees", 0.f, &spot->outerCutoff, 0.7f, 0.01f, 0.001f); nk_property_float(ctx, "Outer Cutoff Degrees", 0.f, &spot->outerCutoff, 0.7f, 0.01f, 0.001f);
nk_tree_pop(ctx); nk_tree_pop(ctx);
} }
} }
*/ */

View file

@ -4,11 +4,11 @@
#include <stdint.h> #include <stdint.h>
struct mLight { struct mLight {
struct gameobject *go; struct gameobject *go;
uint8_t color[3]; uint8_t color[3];
float strength; float strength;
int dynamic; int dynamic;
int on; int on;
}; };
/* /*
@ -21,7 +21,7 @@ struct mPointLight {
struct mPointLight *MakePointlight(); struct mPointLight *MakePointlight();
void pointlight_prepshader(struct mPointLight *light, void pointlight_prepshader(struct mPointLight *light,
struct shader *shader, int num); struct shader *shader, int num);
void pointlights_prepshader(struct shader *shader); void pointlights_prepshader(struct shader *shader);
@ -39,7 +39,7 @@ struct mSpotLight {
struct mSpotLight *MakeSpotlight(); struct mSpotLight *MakeSpotlight();
void spotlight_gui(struct mSpotLight *light); void spotlight_gui(struct mSpotLight *light);
void spotlight_prepshader(struct mSpotLight *light, struct shader *shader, void spotlight_prepshader(struct mSpotLight *light, struct shader *shader,
int num); int num);
void spotlights_prepshader(struct shader *shader); void spotlights_prepshader(struct shader *shader);
@ -49,7 +49,7 @@ struct mDirectionalLight {
}; };
void dlight_prepshader(struct mDirectionalLight *light, void dlight_prepshader(struct mDirectionalLight *light,
struct shader *shader); struct shader *shader);
struct mDirectionalLight *MakeDLight(); struct mDirectionalLight *MakeDLight();
extern struct mDirectionalLight *dLight; extern struct mDirectionalLight *dLight;

View file

@ -4,122 +4,94 @@
#include "shader.h" #include "shader.h"
#include "texture.h" #include "texture.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
void DrawMesh(struct mesh *mesh, struct shader *shader) void DrawMesh(struct mesh *mesh, struct shader *shader) {
{ // bind appropriate textures
// bind appropriate textures uint32_t diffuseNr = 1;
uint32_t diffuseNr = 1; uint32_t specularNr = 1;
uint32_t specularNr = 1; uint32_t normalNr = 1;
uint32_t normalNr = 1; uint32_t heightNr = 1;
uint32_t heightNr = 1;
for (int i = 0; i < (mesh->te - mesh->textures); i++) { // for (int i = 0; i < (mesh->te - mesh->textures); i++) {
// glActiveTexture(GL_TEXTURE0 + i); // active proper texture unit before binding // glActiveTexture(GL_TEXTURE0 + i); // active proper texture unit before binding
// retrieve texture number (the N in diffuse_textureN) // retrieve texture number (the N in diffuse_textureN)
char number = 0; // char number = 0;
// TODO: malloc every single frame ... nope! Change to stack // TODO: malloc every single frame ... nope! Change to stack
/*char *name = malloc(sizeof(char) *(strlen(mesh->textures[i].type) + 2));*/ /*char *name = malloc(sizeof(char) *(strlen(mesh->textures[i].type) + 2));*/
/* /*
if (mesh->textures[i].type == TEX_DIFF) // if (mesh->textures[i].type == TEX_DIFF)
number = diffuseNr++; // number = diffuseNr++;
else if (mesh->textures[i].type == TEX_SPEC) // else if (mesh->textures[i].type == TEX_SPEC)
number = specularNr++; // number = specularNr++;
else if (mesh->textures[i].type == TEX_NORM) // else if (mesh->textures[i].type == TEX_NORM)
number = normalNr++; // number = normalNr++;
else if (mesh->textures[i].type == TEX_HEIGHT) // else if (mesh->textures[i].type == TEX_HEIGHT)
number = heightNr++; // number = heightNr++;
*/ */
/* /*
glUniform1i(glGetUniformLocation(shader->id, name), i); glUniform1i(glGetUniformLocation(shader->id, name), i);
glBindTexture(GL_TEXTURE_2D, mesh->textures[i].id); glBindTexture(GL_TEXTURE_2D, mesh->textures[i].id);
free(name); free(name);
*/ */
}
// draw mesh
glBindVertexArray(mesh->VAO);
DrawMeshAgain(mesh);
// DEBUG
// triCount += indices.size() / 3;
} }
void DrawMeshAgain(struct mesh *mesh) {
void DrawMeshAgain(struct mesh *mesh)
{
} }
struct mesh *MakeMesh(struct Vertex *vertices, struct Vertex *ve, void setupmesh(struct mesh *mesh) {
uint32_t * indices, uint32_t * ie, /*
struct Texture *textures, struct Texture *te) // create buffers/arrays
{ glGenVertexArrays(1, &mesh->VAO);
struct mesh *newmesh = (struct mesh *) malloc(sizeof(struct mesh)); glGenBuffers(1, &mesh->VBO);
newmesh->vertices = vertices; glGenBuffers(1, &mesh->EBO);
newmesh->ve = ve;
newmesh->indices = indices;
newmesh->ie = ie;
newmesh->textures = textures;
newmesh->te = te;
setupmesh(newmesh); glBindVertexArray(mesh->VAO);
return newmesh; // load data into vertex buffers
} glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO);
void setupmesh(struct mesh *mesh)
{ // The effect is that we can simply pass a pointer to the struct and it translates perfectly to vevc array which
/* // again translates to 3/2 floats which translates to a byte array.
// create buffers/arrays glBufferData(GL_ARRAY_BUFFER,
glGenVertexArrays(1, &mesh->VAO); (mesh->ve - mesh->vertices) * sizeof(struct Vertex),
glGenBuffers(1, &mesh->VBO); &mesh->vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &mesh->EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->EBO);
glBindVertexArray(mesh->VAO); glBufferData(GL_ELEMENT_ARRAY_BUFFER,
// load data into vertex buffers (mesh->ie - mesh->indices) * sizeof(uint32_t),
glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO); &mesh->indices[0], GL_STATIC_DRAW);
// set the vertex attribute pointers
// The effect is that we can simply pass a pointer to the struct and it translates perfectly to vevc array which // vertex Positions
// again translates to 3/2 floats which translates to a byte array. glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), NULL);
(mesh->ve - mesh->vertices) * sizeof(struct Vertex), // vertex normals
&mesh->vertices[0], GL_STATIC_DRAW); glEnableVertexAttribArray(1);
// glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, Normal[3]));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->EBO); // vertex texture coords
glBufferData(GL_ELEMENT_ARRAY_BUFFER, glEnableVertexAttribArray(2);
(mesh->ie - mesh->indices) * sizeof(uint32_t), // glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, TexCoords[2]));
&mesh->indices[0], GL_STATIC_DRAW); // vertex tangent
glEnableVertexAttribArray(3);
// set the vertex attribute pointers // glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, Tangent[3]));
// vertex Positions // vertex bitangent
glEnableVertexAttribArray(0); glEnableVertexAttribArray(4);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), NULL); // glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, Bitangent[3]));
// vertex normals
glEnableVertexAttribArray(1); // Bone ids
// glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, Normal[3])); glEnableVertexAttribArray(5);
// vertex texture coords glVertexAttribPointer(5, 4, GL_INT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex,
glEnableVertexAttribArray(2); m_BoneIDs
// glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, TexCoords[2])); [MAX_BONE_INFLUENCE]));
// vertex tangent
glEnableVertexAttribArray(3); // Weights
// glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, Tangent[3])); glEnableVertexAttribArray(6);
// vertex bitangent // glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, m_Weights));
glEnableVertexAttribArray(4);
// glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, Bitangent[3])); glBindVertexArray(0);
// Bone ids */
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_INT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex,
m_BoneIDs
[MAX_BONE_INFLUENCE]));
// Weights
glEnableVertexAttribArray(6);
// glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), offsetof(struct Vertex, m_Weights));
glBindVertexArray(0);
*/
} }

View file

@ -2,40 +2,20 @@
#define MESH_H #define MESH_H
#include "mathc.h" #include "mathc.h"
#include "sokol/sokol_gfx.h"
#include <stdint.h> #include <stdint.h>
struct shader; struct shader;
struct Texture; struct Texture;
#define MAX_BONE_INFLUENCE 4
struct Vertex {
mfloat_t Position[3];
mfloat_t Normal[3];
mfloat_t TexCoords[2];
mfloat_t Tangent[3];
mfloat_t Bitangent[3];
int m_BoneIDs[MAX_BONE_INFLUENCE];
float m_Weights[MAX_BONE_INFLUENCE];
};
struct mesh { struct mesh {
struct Vertex *vertices; sg_bindings bind;
struct Vertex *ve; uint32_t face_count;
uint32_t *indices;
uint32_t *ie;
struct Texture *textures;
struct Texture *te;
uint32_t VAO, VBO, EBO;
}; };
struct mesh *MakeMesh(struct Vertex *vertices, struct Vertex *ve, struct mesh *MakeMesh(struct Vertex *vertices, struct Vertex *ve, uint32_t *indices, uint32_t *ie, struct Texture *textures, struct Texture *te);
uint32_t * indices, uint32_t * ie, void setupmesh(struct mesh *mesh); /* Loads mesh into the GPU */
struct Texture *textures, struct Texture *te);
void setupmesh(struct mesh *mesh); /* Loads mesh into the GPU */
void DrawMesh(struct mesh *mesh, struct shader *shader); void DrawMesh(struct mesh *mesh, struct shader *shader);
void DrawMeshAgain(struct mesh *mesh); /* Draws whatever mesh was drawn last */ void DrawMeshAgain(struct mesh *mesh); /* Draws whatever mesh was drawn last */
#endif #endif

View file

@ -5,10 +5,27 @@
#include "resources.h" #include "resources.h"
#include "shader.h" #include "shader.h"
#include "stb_ds.h" #include "stb_ds.h"
#include "font.h"
#include "openglrender.h"
// #define HANDMADE_MATH_USE_TURNS
#include "HandmadeMath.h"
#include "math.h"
#include "time.h"
#define CGLTF_IMPLEMENTATION
#include <cgltf.h> #include <cgltf.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "texture.h"
#include "mathc.h"
#include "sokol/sokol_gfx.h"
static struct { static struct {
char *key; char *key;
struct Texture *value; struct Texture *value;
@ -18,6 +35,59 @@ static void processnode();
static void processmesh(); static void processmesh();
static void processtexture(); static void processtexture();
static sg_shader model_shader;
static sg_pipeline model_pipe;
void model_init() {
YughWarn("Creating model");
model_shader = sg_make_shader(&(sg_shader_desc){
.vs.source = slurp_text("shaders/diffuse_v.glsl"),
.fs.source = slurp_text("shaders/diffuse_f.glsl"),
.vs.uniform_blocks[0] = {
.size = sizeof(float) * 16 * 4,
.uniforms = {
[0] = {.name = "vp", .type = SG_UNIFORMTYPE_MAT4},
[1] = {.name = "model", .type = SG_UNIFORMTYPE_MAT4},
[2] = {.name = "proj", .type = SG_UNIFORMTYPE_MAT4},
[3] = {.name = "lsm", .type = SG_UNIFORMTYPE_MAT4},
}},
.fs.uniform_blocks[0] = {
.size = sizeof(float) * 3 * 5,
.uniforms = {
[0] = {.name = "point_pos", .type = SG_UNIFORMTYPE_FLOAT3},
[1] = {.name = "dir_dir", .type = SG_UNIFORMTYPE_FLOAT3},
[2] = {.name = "view_pos", .type = SG_UNIFORMTYPE_FLOAT3},
[3] = {.name = "spot_pos", .type = SG_UNIFORMTYPE_FLOAT3},
[4] = {.name = "spot_dir", .type = SG_UNIFORMTYPE_FLOAT3},
},
},
.fs.images[0] = {.name = "diffuse", .image_type = SG_IMAGETYPE_2D, .sampler_type = SG_SAMPLERTYPE_FLOAT},
.fs.images[1] = { .name = "normmap", .image_type = SG_IMAGETYPE_2D, .sampler_type = SG_SAMPLERTYPE_FLOAT},
.fs.images[2] = {.name = "shadow_map", .image_type = SG_IMAGETYPE_2D, .sampler_type = SG_SAMPLERTYPE_FLOAT},
});
model_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = model_shader,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT3,
[0].buffer_index = 0, /* position */
[1].format = SG_VERTEXFORMAT_FLOAT2,
[1].buffer_index = 1, /* tex coords */
[2].format = SG_VERTEXFORMAT_FLOAT3,
[2].buffer_index = 2, /* normal */
},
},
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_FRONT,
.depth.write_enabled = true,
.depth.compare = SG_COMPAREFUNC_LESS_EQUAL
});
}
struct model *GetExistingModel(const char *path) { struct model *GetExistingModel(const char *path) {
if (!path || path[0] == '\0') return NULL; if (!path || path[0] == '\0') return NULL;
@ -27,8 +97,18 @@ struct model *GetExistingModel(const char *path) {
return MakeModel(path); return MakeModel(path);
} }
/* TODO: Make this a hash compare for speedup */ cgltf_attribute *get_attr_type(cgltf_primitive p, cgltf_attribute_type t)
{
for (int i = 0; i < p.attributes_count; i++) {
if (p.attributes[i].type == t)
return &p.attributes[i];
}
return NULL;
}
struct model *MakeModel(const char *path) { struct model *MakeModel(const char *path) {
YughWarn("Making the model from %s.", path);
cgltf_options options = {0}; cgltf_options options = {0};
cgltf_data *data = NULL; cgltf_data *data = NULL;
cgltf_result result = cgltf_parse_file(&options, path, &data); cgltf_result result = cgltf_parse_file(&options, path, &data);
@ -45,188 +125,166 @@ struct model *MakeModel(const char *path) {
return NULL; return NULL;
} }
struct model *model = malloc(sizeof(struct model)); struct model *model = calloc(1, sizeof(*model));
/* TODO: Optimize by grouping by material. One material per draw. */
YughWarn("Model has %d materials.", data->materials_count);
model->meshes = malloc(sizeof(struct mesh) * data->meshes_count); float vs[65535*3];
uint16_t idxs[65535];
for (int i = 0; i < data->nodes_count; i++) { for (int i = 0; i < data->meshes_count; i++) {
cgltf_mesh *mesh = &data->meshes[i];
if (data->nodes[i].mesh) { struct mesh newmesh = {0};
cgltf_mesh *mesh = data->nodes[i].mesh; arrput(model->meshes,newmesh);
for (int j = 0; j < mesh->primitives_count; j++) { YughWarn("Making mesh %d. It has %d primitives.", i, mesh->primitives_count);
cgltf_primitive primitive = mesh->primitives[j];
for (int j = 0; j < mesh->primitives_count; j++) {
for (int k = 0; k < primitive.attributes_count; k++) { cgltf_primitive primitive = mesh->primitives[j];
cgltf_attribute attribute = primitive.attributes[k];
if (primitive.indices) {
switch (attribute.type) { int c = primitive.indices->count;
memcpy(idxs, cgltf_buffer_view_data(primitive.indices->buffer_view), sizeof(uint16_t) * c);
case cgltf_attribute_type_position:
// float *vs = malloc(sizeof(float) * cgltf_accessor_unpack_floats(attribute.accessor, NULL, attribute.accessor.count); model->meshes[j].bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
// cgltf_accessor_unpack_floats(attribute.accessor, vs, attribute.accessor.count); .data.ptr = idxs,
.data.size = sizeof(uint16_t) * c,
.type = SG_BUFFERTYPE_INDEXBUFFER});
model->meshes[j].face_count = c;
} else {
YughWarn("Model does not have indices. Generating them.");
int c = primitive.attributes[0].data->count;
model->meshes[j].face_count = c;
for (int z = 0; z < c; z++)
idxs[z] = z;
model->meshes[j].bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = idxs,
.data.size = sizeof(uint16_t) * c,
.type = SG_BUFFERTYPE_INDEXBUFFER});
}
if (primitive.material->has_pbr_metallic_roughness && primitive.material->pbr_metallic_roughness.base_color_texture.texture) {
// YughWarn("Texture is %s.", primitive.material->pbr_metallic_roughness.base_color_texture.texture->image->uri);
model->meshes[j].bind.fs_images[0] = texture_pullfromfile(primitive.material->pbr_metallic_roughness.base_color_texture.texture->image->uri)->id;
} else
model->meshes[j].bind.fs_images[0] = texture_pullfromfile("k")->id;
cgltf_texture *tex;
if (tex = primitive.material->normal_texture.texture) {
model->meshes[j].bind.fs_images[1] = texture_pullfromfile(tex->image->uri)->id;
} else
model->meshes[j].bind.fs_images[1] = texture_pullfromfile("k")->id;
model->meshes[j].bind.fs_images[2] = ddimg;
int has_norm = 0;
for (int k = 0; k < primitive.attributes_count; k++) {
cgltf_attribute attribute = primitive.attributes[k];
int n = cgltf_accessor_unpack_floats(attribute.data, NULL, 0); /* floats per element x num elements */
cgltf_accessor_unpack_floats(attribute.data, vs, n);
switch (attribute.type) {
case cgltf_attribute_type_position:
model->meshes[j].bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = vs,
.data.size = sizeof(float) * n});
break; break;
case cgltf_attribute_type_normal: case cgltf_attribute_type_normal:
break; has_norm = 1;
model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = vs,
.data.size = sizeof(float) * n});
break;
case cgltf_attribute_type_tangent:
break;
case cgltf_attribute_type_tangent: case cgltf_attribute_type_texcoord:
break; model->meshes[j].bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = vs,
case cgltf_attribute_type_texcoord: .data.size = sizeof(float) * n});
break; break;
}
} }
} }
}
if (!has_norm) {
YughWarn("Model does not have normals. Generating them.");
float norms[3 * model->meshes[j].face_count];
cgltf_attribute *pa = get_attr_type(primitive, cgltf_attribute_type_position);
int n = cgltf_accessor_unpack_floats(pa->data, NULL,0);
float ps[n];
cgltf_accessor_unpack_floats(pa->data,ps,n);
for (int i = 0; i < model->meshes[j].face_count/3; i++) {
int o = i*9;
HMM_Vec3 a = {ps[o], ps[o+1],ps[o+2]};
o += 3;
HMM_Vec3 b = {ps[o], ps[o+1],ps[o+2]};
o += 3;
HMM_Vec3 c = {ps[o], ps[o+1],ps[o+2]};
HMM_Vec3 norm = HMM_NormV3(HMM_Cross(HMM_SubV3(b,a), HMM_SubV3(c,a)));
for (int j = 0; j < 3; j++) {
norms[i*9+j*3+0] = norm.X;
norms[i*9+j*3+1] = norm.Y;
norms[i*9+j*3+2] = norm.Z;
}
}
model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = norms,
.data.size = sizeof(float) * model->meshes[j].face_count * 3
});
}
}
}
return model;
}
HMM_Vec3 eye = {50,10,5};
void draw_model(struct model *model, HMM_Mat4 amodel, HMM_Mat4 lsm) {
HMM_Mat4 proj = HMM_Perspective_RH_ZO(45, 1200.f / 720, 0.1, 10000);
HMM_Vec3 center = {0.f, 0.f, 0.f};
HMM_Vec3 up = {0.f, 1.f, 0.f};
HMM_Mat4 view = HMM_LookAt_RH(eye, center, up);
HMM_Mat4 vp = HMM_MulM4(proj, view);
HMM_Mat4 mvp = HMM_MulM4(vp, amodel);
HMM_Vec3 lp = {1, 1, 1};
HMM_Vec3 dir_dir = HMM_NormV3(HMM_SubV3(center, dirl_pos));
HMM_Mat4 m2[4];
m2[0] = view;
m2[1] = amodel;
m2[2] = proj;
m2[3] = lsm;
HMM_Vec3 f_ubo[5];
f_ubo[0] = lp;
f_ubo[1] = dir_dir;
f_ubo[2] = eye;
f_ubo[3] = eye;
f_ubo[4] = eye;
sg_apply_pipeline(model_pipe);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(m2));
sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, SG_RANGE_REF(f_ubo));
for (int i = 0; i < arrlen(model->meshes); i++) {
sg_apply_bindings(&model->meshes[i].bind);
sg_draw(0, model->meshes[i].face_count, 1);
} }
} }
/* TODO: DELETE
static void processnode() {
for (uint32_t i = 0; i < node->mNumMeshes; i++) {
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
*mp = processMesh(mesh, scene);
mp++;
}
for (uint32_t i = 0; i < node->mNumChildren; i++) {
processnode(node->mChildren[i], scene);
}
}
*/
static void processmesh() {
/*
Vertex *vertices =
(Vertex *) malloc(sizeof(Vertex) * mesh->mNumVertices);
Vertex *vp = vertices + mesh->mNumVertices;
Vertex *p = vertices;
for (int i = 0; i < mesh->mNumVertices; i++) {
// positions
(p + i)->Position.x = mesh->mVertices[i][0];
(p + i)->Position.y = mesh->mVertices[i][1];
(p + i)->Position.z = mesh->mVertices[i][2];
// normals
if (mesh->HasNormals()) {
(p + i)->Normal.x = mesh->mNormals[i][0];
(p + i)->Normal.y = mesh->mNormals[i].y;
(p + i)->Normal.z = mesh->mNormals[i].z;
}
// texture coordinates
if (mesh->mTextureCoords[0]) {
glm::vec2 vec;
// a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
(p + i)->TexCoords.x = mesh->mTextureCoords[0][i].x;
(p + i)->TexCoords.y = mesh->mTextureCoords[0][i].y;
// tangent
(p + i)->Tangent.x = mesh->mTangents[i].x;
(p + i)->Tangent.y = mesh->mTangents[i].y;
(p + i)->Tangent.z = mesh->mTangents[i].z;
// bitangent
(p + i)->Bitangent.x = mesh->mBitangents[i].x;
(p + i)->Bitangent.y = mesh->mBitangents[i].y;
(p + i)->Bitangent.z = mesh->mBitangents[i].z;
} else
(p + i)->TexCoords = glm::vec2(0.0f, 0.0f);
}
// TODO: Done quickly, find better way. Go through for loop twice!
int numindices = 0;
// now walk through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
for (uint32_t i = 0; i < mesh->mNumFaces; i++) {
numindices += mesh->mFaces[i].mNumIndices;
}
uint32_t *indices = (uint32_t *) malloc(sizeof(uint32_t) * numindices);
uint32_t *ip = indices;
for (uint32_t i = 0; i < mesh->mNumFaces; i++) {
for (uint32_t j = 0; j < mesh->mFaces[i].mNumIndices; j++) {
*ip = mesh->mFaces[i].mIndices[j];
ip++;
}
}
// std::vector<Texture> textures;
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
// TODO: Allocating 100 to be safe, can probably be way less
textures_loaded = (Texture *) malloc(sizeof(Texture) * 100);
tp = textures_loaded;
// we assume a convention for sampler names in the shaders. Each diffuse texture should be named
// as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER.
// Same applies to other texture as the following list summarizes:
// diffuse: texture_diffuseN
// specular: texture_specularN
// normal: texture_normalN
// 1. diffuse maps
loadMaterialTextures(material, aiTextureType_DIFFUSE,
"texture_diffuse");
// 2. specular maps
loadMaterialTextures(material, aiTextureType_SPECULAR,
"texture_specular");
// 3. normal maps
loadMaterialTextures(material, aiTextureType_NORMALS,
"texture_normal");
// 4. height maps
loadMaterialTextures(material, aiTextureType_AMBIENT,
"texture_height");
// return a mesh object created from the extracted mesh data
return Mesh(vertices, vp, indices, ip, textures_loaded, tp);
*/
}
// TODO: This routine mallocs inside the function
static void processtexture() {
/*
for (uint32_t i = 0; i < mat->GetTextureCount(type); i++) {
aiString str;
mat->GetTexture(type, i, &str);
for (Texture * tpp = textures_loaded; tpp != tp; tpp++) {
if (strcmp(tpp->path, str.data) == 0)
goto next; // Check if we already have this texture
}
tp->id = TextureFromFile(str.data, this->directory);
tp->type = (char *) malloc(sizeof(char) * strlen(typeName));
strcpy(tp->type, typeName);
tp->path = (char *) malloc(sizeof(char) * strlen(str.data));
strcpy(tp->path, str.data);
tp++;
next:;
}
*/
}
void draw_models(struct model *model, struct shader *shader)
{
}
// TODO: Come back to this; simple optimization
void draw_model(struct model *model, struct shader *shader) {
}

View file

@ -1,12 +1,14 @@
#ifndef MODEL_H #ifndef MODEL_H
#define MODEL_H #define MODEL_H
struct mesh; #include "mesh.h"
#include "HandmadeMath.h"
extern HMM_Vec3 eye;
struct shader; struct shader;
struct model { struct model {
struct mesh *meshes; struct mesh *meshes;
struct mesh *mp;
}; };
/* Get the model at a path, or create and return if it doesn't exist */ /* Get the model at a path, or create and return if it doesn't exist */
@ -18,7 +20,9 @@ struct model *MakeModel(const char *path);
/* Load a model from memory into the GPU */ /* Load a model from memory into the GPU */
void loadmodel(struct model *model); void loadmodel(struct model *model);
void draw_model(struct model *model, struct shader *shader); void model_init();
void draw_model(struct model *model, HMM_Mat4 amodel, HMM_Mat4 lsm);
void draw_models(struct model *model, struct shader *shader); void draw_models(struct model *model, struct shader *shader);
#endif #endif

View file

@ -1,9 +1,9 @@
#include "skybox.h" #include "skybox.h"
#include "shader.h"
#include "camera.h" #include "camera.h"
#include <string.h> #include "shader.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "openglrender.h" #include "openglrender.h"
@ -48,82 +48,79 @@ static const float skyboxVertices[216] = {
1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f 1.0f, -1.0f, 1.0f};
};
struct mSkybox *MakeSkybox(const char *cubemap) struct mSkybox *MakeSkybox(const char *cubemap) {
{ /*
/* struct mSkybox *newskybox = malloc(sizeof(struct mSkybox));
struct mSkybox *newskybox = malloc(sizeof(struct mSkybox));
newskybox->shader = MakeShader("skyvert.glsl", "skyfrag.glsl"); newskybox->shader = MakeShader("skyvert.glsl", "skyfrag.glsl");
shader_compile(newskybox->shader); shader_compile(newskybox->shader);
glGenVertexArrays(1, &newskybox->VAO); glGenVertexArrays(1, &newskybox->VAO);
glGenBuffers(1, &newskybox->VBO); glGenBuffers(1, &newskybox->VBO);
glBindVertexArray(newskybox->VAO); glBindVertexArray(newskybox->VAO);
glBindBuffer(GL_ARRAY_BUFFER, newskybox->VBO); glBindBuffer(GL_ARRAY_BUFFER, newskybox->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
(void *) 0); (void *) 0);
shader_use(newskybox->shader); shader_use(newskybox->shader);
shader_setint(newskybox->shader, "skybox", 0); shader_setint(newskybox->shader, "skybox", 0);
*/ */
/* /*
const char *faces[6] = const char *faces[6] =
{ "right.jpg", "left.jpg", "top.jpg", "bottom.jpg", "front.jpg", { "right.jpg", "left.jpg", "top.jpg", "bottom.jpg", "front.jpg",
"back.jpg" "back.jpg"
}; };
*/ */
/* /*
glGenTextures(1, &newskybox->id); glGenTextures(1, &newskybox->id);
glBindTexture(GL_TEXTURE_CUBE_MAP, newskybox->id); glBindTexture(GL_TEXTURE_CUBE_MAP, newskybox->id);
*/ */
/*char buf[100] = { '\0' };*/ /*char buf[100] = { '\0' };*/
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
/* /*
buf[0] = '\0'; buf[0] = '\0';
strcat(buf, cubemap); strcat(buf, cubemap);
strcat(buf, "/"); strcat(buf, "/");
strcat(buf, faces[i]); strcat(buf, faces[i]);
IMG_Load(buf); IMG_Load(buf);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 2048, glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 2048,
2048, 0, GL_RGB, GL_UNSIGNED_BYTE, data->pixels); 2048, 0, GL_RGB, GL_UNSIGNED_BYTE, data->pixels);
*/ */
} }
/* /*
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE); GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE); GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R,
GL_CLAMP_TO_EDGE); GL_CLAMP_TO_EDGE);
return newskybox; return newskybox;
*/ */
} }
void skybox_draw(const struct mSkybox *skybox, void skybox_draw(const struct mSkybox *skybox,
const struct mCamera *camera) const struct mCamera *camera) {
{ /*
/* shader_use(skybox->shader);
shader_use(skybox->shader);
mfloat_t view[16] = { 0.f }; mfloat_t view[16] = { 0.f };
getviewmatrix(view, camera); getviewmatrix(view, camera);
shader_setmat4(skybox->shader, "skyview", view); shader_setmat4(skybox->shader, "skyview", view);
// skybox cube // skybox cube
glBindVertexArray(skybox->VAO); glBindVertexArray(skybox->VAO);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->id); glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->id);
glDrawArrays(GL_TRIANGLES, 0, 36); glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0); glBindVertexArray(0);
*/ */
} }

View file

@ -4,14 +4,14 @@
struct mCamera; struct mCamera;
struct mSkybox { struct mSkybox {
unsigned int VAO; unsigned int VAO;
unsigned int VBO; unsigned int VBO;
unsigned int id; unsigned int id;
struct shader *shader; struct shader *shader;
}; };
struct mSkybox *MakeSkybox(const char *cubemap); struct mSkybox *MakeSkybox(const char *cubemap);
void skybox_draw(const struct mSkybox *skybox, void skybox_draw(const struct mSkybox *skybox,
const struct mCamera *camera); const struct mCamera *camera);
#endif #endif

3553
source/engine/HandmadeMath.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,311 +0,0 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */

View file

@ -1,51 +1,51 @@
#include "anim.h" #include "anim.h"
#include "stb_ds.h"
#include "log.h" #include "log.h"
#include "stb_ds.h"
struct anim make_anim() { struct anim make_anim() {
struct anim a = {0}; struct anim a = {0};
a.interp = 1; a.interp = 1;
return a; return a;
} }
void free_anim(struct anim a) { void free_anim(struct anim a) {
arrfree(a.frames); arrfree(a.frames);
} }
struct anim anim_add_keyframe(struct anim a, struct keyframe key) { struct anim anim_add_keyframe(struct anim a, struct keyframe key) {
arrput(a.frames, key); arrput(a.frames, key);
return a; return a;
} }
double interval(struct keyframe a, struct keyframe b, double t) { double interval(struct keyframe a, struct keyframe b, double t) {
return (t - a.time) / (b.time - a.time); return (t - a.time) / (b.time - a.time);
} }
double near_val(struct anim anim, double t) { double near_val(struct anim anim, double t) {
for (int i = 0; i < arrlen(anim.frames) - 1; i++) { for (int i = 0; i < arrlen(anim.frames) - 1; i++) {
if (t > anim.frames[i+1].time) if (t > anim.frames[i + 1].time)
continue; continue;
return (interval(anim.frames[i], anim.frames[i+1], t) >= 0.5f ? anim.frames[i+1].val : anim.frames[i].val); return (interval(anim.frames[i], anim.frames[i + 1], t) >= 0.5f ? anim.frames[i + 1].val : anim.frames[i].val);
} }
return arrlast(anim.frames).val; return arrlast(anim.frames).val;
} }
double lerp_val(struct anim anim, double t) { double lerp_val(struct anim anim, double t) {
for (int i = 0; i < arrlen(anim.frames) - 1; i++) { for (int i = 0; i < arrlen(anim.frames) - 1; i++) {
if (t > anim.frames[i+1].time) if (t > anim.frames[i + 1].time)
continue; continue;
double intv = interval(anim.frames[i], anim.frames[i+1], t); double intv = interval(anim.frames[i], anim.frames[i + 1], t);
return ((1 - intv) * anim.frames[i].val) + (intv * anim.frames[i+1].val); return ((1 - intv) * anim.frames[i].val) + (intv * anim.frames[i + 1].val);
} }
return arrlast(anim.frames).val; return arrlast(anim.frames).val;
} }
double cubic_val(struct anim anim, double t) { double cubic_val(struct anim anim, double t) {
@ -53,8 +53,8 @@ double cubic_val(struct anim anim, double t) {
} }
double anim_val(struct anim anim, double t) { double anim_val(struct anim anim, double t) {
if (anim.interp == 0) if (anim.interp == 0)
return near_val(anim, t); return near_val(anim, t);
return lerp_val(anim, t); return lerp_val(anim, t);
} }

View file

@ -2,19 +2,18 @@
#define ANIM_H #define ANIM_H
struct keyframe { struct keyframe {
double time; double time;
double val; double val;
}; };
struct anim { struct anim {
struct keyframe *frames; struct keyframe *frames;
int loop; int loop;
int interp; int interp;
}; };
struct anim make_anim(); struct anim make_anim();
struct anim anim_add_keyframe(struct anim a, struct keyframe f); struct anim anim_add_keyframe(struct anim a, struct keyframe f);
double anim_val(struct anim anim, double t); double anim_val(struct anim anim, double t);
#endif #endif

View file

@ -3,70 +3,64 @@
#include "gameobject.h" #include "gameobject.h"
#include "input.h" #include "input.h"
const float CAMERA_MINSPEED = 1.f; const float CAMERA_MINSPEED = 1.f;
const float CAMERA_MAXSPEED = 300.f; const float CAMERA_MAXSPEED = 300.f;
const float CAMERA_ROTATESPEED = 6.f; const float CAMERA_ROTATESPEED = 6.f;
void cam_goto_object(struct mCamera *cam, struct mTransform *transform) void cam_goto_object(struct mCamera *cam, struct mTransform *transform) {
{ mfloat_t fwd[3] = {0.f};
mfloat_t fwd[3] = { 0.f }; vec3_subtract(cam->transform.position, transform->position,
vec3_subtract(cam->transform.position, transform->position, vec3_multiply_f(fwd, trans_forward(fwd, transform),
vec3_multiply_f(fwd, trans_forward(fwd, transform), 10.f));
10.f));
} }
void cam_inverse_goto(struct mCamera *cam, struct mTransform *transform) void cam_inverse_goto(struct mCamera *cam, struct mTransform *transform) {
{ mfloat_t fwd[3] = {0.f};
mfloat_t fwd[3] = { 0.f }; vec3_add(transform->position, cam->transform.position,
vec3_add(transform->position, cam->transform.position, vec3_multiply_f(fwd, trans_forward(fwd, &cam->transform),
vec3_multiply_f(fwd, trans_forward(fwd, &cam->transform), 10.f));
10.f));
} }
mfloat_t *getviewmatrix(mfloat_t view[16], mfloat_t *getviewmatrix(mfloat_t view[16],
const struct mCamera *const camera) const struct mCamera *const camera) {
{ mfloat_t fwd[3] = {0.f};
mfloat_t fwd[3] = { 0.f }; mfloat_t look[3] = {0.f};
mfloat_t look[3] = { 0.f }; vec3_rotate_quat(fwd, FORWARD, camera->transform.rotation);
vec3_rotate_quat(fwd, FORWARD, camera->transform.rotation); vec3_add(look, camera->transform.position, fwd);
vec3_add(look, camera->transform.position, fwd); mat4_look_at(view, camera->transform.position, look, UP);
mat4_look_at(view, camera->transform.position, look, UP); return view;
return view; /*return mat4_look_at(view, ncam.transform.position,
/*return mat4_look_at(view, ncam.transform.position, vec3_add(look, ncam.transform.position,
vec3_add(look, ncam.transform.position, trans_forward(fwd, &ncam.transform)),
trans_forward(fwd, &ncam.transform)), UP); */
UP); */
} }
void camera_2d_update(struct mCamera *camera, float deltaT) void camera_2d_update(struct mCamera *camera, float deltaT) {
{ static mfloat_t frame[3];
static mfloat_t frame[3]; vec3_zero(frame);
vec3_zero(frame); if (action_down(GLFW_KEY_W))
if (action_down(GLFW_KEY_W)) vec3_add(frame, frame, UP);
vec3_add(frame, frame, UP); if (action_down(GLFW_KEY_S))
if (action_down(GLFW_KEY_S)) vec3_add(frame, frame, DOWN);
vec3_add(frame, frame, DOWN); if (action_down(GLFW_KEY_A))
if (action_down(GLFW_KEY_A)) vec3_add(frame, frame, LEFT);
vec3_add(frame, frame, LEFT); if (action_down(GLFW_KEY_D))
if (action_down(GLFW_KEY_D)) vec3_add(frame, frame, RIGHT);
vec3_add(frame, frame, RIGHT);
float speedMult = action_down(GLFW_KEY_LEFT_SHIFT) ? 2.f : 1.f; float speedMult = action_down(GLFW_KEY_LEFT_SHIFT) ? 2.f : 1.f;
if (!vec3_is_zero(frame)) {
vec3_normalize(frame, frame);
vec3_add(camera->transform.position, camera->transform.position,
vec3_multiply_f(frame, frame,
camera->speed * speedMult * deltaT));
}
if (!vec3_is_zero(frame)) {
vec3_normalize(frame, frame);
vec3_add(camera->transform.position, camera->transform.position,
vec3_multiply_f(frame, frame,
camera->speed * speedMult * deltaT));
}
} }
/* /*
void camera_update(struct mCamera * camera, float mouseX, float mouseY, void camera_update(struct mCamera * camera, float mouseX, float mouseY,
const uint8_t * keystate, int32_t mouseWheelY, const uint8_t * keystate, int32_t mouseWheelY,
float deltaTime) float deltaTime)
{ {
// if (SDL_GetRelativeMouseMode()) vec3_zero(camera->frame_move); // if (SDL_GetRelativeMouseMode()) vec3_zero(camera->frame_move);
@ -74,43 +68,43 @@ void camera_update(struct mCamera * camera, float mouseX, float mouseY,
vec3_zero(camera->frame_move); vec3_zero(camera->frame_move);
if (currentKeystates[SDL_SCANCODE_W]) if (currentKeystates[SDL_SCANCODE_W])
vec3_add(camera->frame_move, camera->frame_move, vec3_add(camera->frame_move, camera->frame_move,
trans_forward(holdvec, &camera->transform)); trans_forward(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_S]) if (currentKeystates[SDL_SCANCODE_S])
vec3_subtract(camera->frame_move, camera->frame_move, vec3_subtract(camera->frame_move, camera->frame_move,
trans_forward(holdvec, &camera->transform)); trans_forward(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_A]) if (currentKeystates[SDL_SCANCODE_A])
vec3_subtract(camera->frame_move, camera->frame_move, vec3_subtract(camera->frame_move, camera->frame_move,
trans_right(holdvec, &camera->transform)); trans_right(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_D]) if (currentKeystates[SDL_SCANCODE_D])
vec3_add(camera->frame_move, camera->frame_move, vec3_add(camera->frame_move, camera->frame_move,
trans_right(holdvec, &camera->transform)); trans_right(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_E]) if (currentKeystates[SDL_SCANCODE_E])
vec3_add(camera->frame_move, camera->frame_move, vec3_add(camera->frame_move, camera->frame_move,
trans_up(holdvec, &camera->transform)); trans_up(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_Q]) if (currentKeystates[SDL_SCANCODE_Q])
vec3_subtract(camera->frame_move, camera->frame_move, vec3_subtract(camera->frame_move, camera->frame_move,
trans_up(holdvec, &camera->transform)); trans_up(holdvec, &camera->transform));
camera->speedMult = currentKeystates[SDL_SCANCODE_LSHIFT] ? 2.f : 1.f; camera->speedMult = currentKeystates[SDL_SCANCODE_LSHIFT] ? 2.f : 1.f;
if (!vec3_is_zero(camera->frame_move)) { if (!vec3_is_zero(camera->frame_move)) {
vec3_normalize(camera->frame_move, camera->frame_move); vec3_normalize(camera->frame_move, camera->frame_move);
vec3_add(camera->transform.position, camera->transform.position, vec3_add(camera->transform.position, camera->transform.position,
vec3_multiply_f(camera->frame_move, camera->frame_move, vec3_multiply_f(camera->frame_move, camera->frame_move,
camera->speed * camera->speedMult * camera->speed * camera->speedMult *
deltaTime)); deltaTime));
} }
// Adjust speed based on mouse wheel // Adjust speed based on mouse wheel
camera->speed = camera->speed =
clampf(camera->speed + mouseWheelY, CAMERA_MINSPEED, clampf(camera->speed + mouseWheelY, CAMERA_MINSPEED,
CAMERA_MAXSPEED); CAMERA_MAXSPEED);
// TODO: Handle this as additive quaternions // TODO: Handle this as additive quaternions
@ -120,9 +114,9 @@ void camera_update(struct mCamera * camera, float mouseX, float mouseY,
if (camera->pitch > 89.f) if (camera->pitch > 89.f)
camera->pitch = 89.f; camera->pitch = 89.f;
if (camera->pitch < -89.f) if (camera->pitch < -89.f)
camera->pitch = -89.f; camera->pitch = -89.f;
mfloat_t qyaw[4] = {0.f}; mfloat_t qyaw[4] = {0.f};
mfloat_t qpitch[4] = {0.f}; mfloat_t qpitch[4] = {0.f};

View file

@ -8,10 +8,10 @@ extern const float CAMERA_MAXSPEED;
extern const float CAMERA_ROTATESPEED; extern const float CAMERA_ROTATESPEED;
struct mCamera { struct mCamera {
struct mTransform transform; struct mTransform transform;
float speed; float speed;
float speedMult; float speedMult;
mfloat_t frame_move[VEC3_SIZE]; mfloat_t frame_move[VEC3_SIZE];
}; };
void camera_2d_update(struct mCamera *camera, float deltaT); void camera_2d_update(struct mCamera *camera, float deltaT);

View file

@ -1,8 +1,7 @@
#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H
#define MAXPATH 256 /* 255 chars + null */
#define MAXPATH 256 /* 255 chars + null */
#define MAXNAME 50 #define MAXNAME 50
#define SCREEN_WIDTH 1280 #define SCREEN_WIDTH 1280

View file

@ -1,206 +1,189 @@
#include "datastream.h" #include "datastream.h"
#include "render.h"
#include "config.h" #include "config.h"
#include "shader.h"
#include "resources.h"
#include "sound.h"
#include <stdbool.h>
#include "log.h"
#include "texture.h"
#include <stdlib.h>
#include "mix.h"
#include "limits.h"
#include "iir.h"
#include "dsp.h" #include "dsp.h"
#include "iir.h"
#include "limits.h"
#include "log.h"
#include "mix.h"
#include "render.h"
#include "resources.h"
#include "shader.h"
#include "sound.h"
#include "texture.h"
#include <stdbool.h>
#include <stdlib.h>
struct shader *vid_shader; struct shader *vid_shader;
static void ds_update_texture(uint32_t unit, uint32_t texture, plm_plane_t * plane) static void ds_update_texture(uint32_t unit, uint32_t texture, plm_plane_t *plane) {
{ /*
/* glActiveTexture(unit);
glActiveTexture(unit); glBindTexture(GL_TEXTURE_2D, texture);
glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, plane->width, plane->height, 0, GL_RED, GL_UNSIGNED_BYTE, plane->data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, plane->width, plane->height, 0, GL_RED, GL_UNSIGNED_BYTE, plane->data); */
*/
} }
static void render_frame(plm_t * mpeg, plm_frame_t * frame, void *user) static void render_frame(plm_t *mpeg, plm_frame_t *frame, void *user) {
{ struct datastream *ds = user;
struct datastream *ds = user; shader_use(ds->shader);
shader_use(ds->shader); /*
/* ds_update_texture(GL_TEXTURE0, ds->texture_y, &frame->y);
ds_update_texture(GL_TEXTURE0, ds->texture_y, &frame->y); ds_update_texture(GL_TEXTURE1, ds->texture_cb, &frame->cb);
ds_update_texture(GL_TEXTURE1, ds->texture_cb, &frame->cb); ds_update_texture(GL_TEXTURE2, ds->texture_cr, &frame->cr);
ds_update_texture(GL_TEXTURE2, ds->texture_cr, &frame->cr); */
*/
} }
static void render_audio(plm_t * mpeg, plm_samples_t * samples, void *user) static void render_audio(plm_t *mpeg, plm_samples_t *samples, void *user) {
{ struct datastream *ds = user;
struct datastream *ds = user; short t;
short t;
for (int i = 0; i < samples->count * CHANNELS; i++) { for (int i = 0; i < samples->count * CHANNELS; i++) {
t = (short)(samples->interleaved[i] * SHRT_MAX); t = (short)(samples->interleaved[i] * SHRT_MAX);
cbuf_push(ds->astream->buf, t*5); cbuf_push(ds->astream->buf, t * 5);
} }
} }
struct Texture *ds_maketexture(struct datastream *ds) struct Texture *ds_maketexture(struct datastream *ds) {
{ /*
/* struct Texture *new = malloc(sizeof(*new));
struct Texture *new = malloc(sizeof(*new)); new->id = ds->texture_cb;
new->id = ds->texture_cb; new->width = 500;
new->width = 500; new->height = 500;
new->height = 500; return new;
return new; */
*/
} }
void ds_openvideo(struct datastream *ds, const char *video, const char *adriver) void ds_openvideo(struct datastream *ds, const char *video, const char *adriver) {
{ // ds_stop(ds);
// ds_stop(ds); char buf[MAXPATH] = {'\0'};
char buf[MAXPATH] = {'\0'}; sprintf(buf, "%s%s", "video/", video);
sprintf(buf, "%s%s", "video/", video); ds->plm = plm_create_with_filename(buf);
ds->plm = plm_create_with_filename(buf);
if (!ds->plm) { if (!ds->plm) {
YughLog(0, 0, "Couldn't open %s", video); YughLog(0, 0, "Couldn't open %s", video);
} }
YughLog(0, 0, "Opened %s - framerate: %f, samplerate: %d, audio streams: %i, duration: %f", YughLog(0, 0, "Opened %s - framerate: %f, samplerate: %d, audio streams: %i, duration: %f",
video, video,
plm_get_framerate(ds->plm), plm_get_framerate(ds->plm),
plm_get_samplerate(ds->plm), plm_get_samplerate(ds->plm),
plm_get_num_audio_streams(ds->plm), plm_get_num_audio_streams(ds->plm),
plm_get_duration(ds->plm) plm_get_duration(ds->plm));
);
ds->astream = soundstream_make(); ds->astream = soundstream_make();
struct dsp_filter astream_filter; struct dsp_filter astream_filter;
astream_filter.data = &ds->astream; astream_filter.data = &ds->astream;
astream_filter.filter = soundstream_fillbuf; astream_filter.filter = soundstream_fillbuf;
//struct dsp_filter lpf = lpf_make(8, 10000); // struct dsp_filter lpf = lpf_make(8, 10000);
struct dsp_filter lpf = lpf_make(1, 200); struct dsp_filter lpf = lpf_make(1, 200);
struct dsp_iir *iir = lpf.data; struct dsp_iir *iir = lpf.data;
iir->in = astream_filter; iir->in = astream_filter;
struct dsp_filter hpf = hpf_make(1, 2000);
struct dsp_iir *hiir = hpf.data;
hiir->in = astream_filter;
struct dsp_filter hpf = hpf_make(1, 2000); /*
struct dsp_iir *hiir = hpf.data; struct dsp_filter llpf = lp_fir_make(20);
hiir->in = astream_filter; struct dsp_fir *fir = llpf.data;
fir->in = astream_filter;
*/
/* // first_free_bus(astream_filter);
struct dsp_filter llpf = lp_fir_make(20);
struct dsp_fir *fir = llpf.data;
fir->in = astream_filter;
*/
//first_free_bus(astream_filter); plm_set_video_decode_callback(ds->plm, render_frame, ds);
plm_set_audio_decode_callback(ds->plm, render_audio, ds);
plm_set_loop(ds->plm, false);
plm_set_video_decode_callback(ds->plm, render_frame, ds); plm_set_audio_enabled(ds->plm, true);
plm_set_audio_decode_callback(ds->plm, render_audio, ds); plm_set_audio_stream(ds->plm, 0);
plm_set_loop(ds->plm, false);
plm_set_audio_enabled(ds->plm, true); // Adjust the audio lead time according to the audio_spec buffer size
plm_set_audio_stream(ds->plm, 0); plm_set_audio_lead_time(ds->plm, BUF_FRAMES / SAMPLERATE);
// Adjust the audio lead time according to the audio_spec buffer size ds->playing = true;
plm_set_audio_lead_time(ds->plm, BUF_FRAMES/SAMPLERATE);
ds->playing = true;
} }
struct datastream *MakeDatastream() struct datastream *MakeDatastream() {
{ struct datastream *newds = malloc(sizeof(*newds));
struct datastream *newds = malloc(sizeof(*newds)); /*
/* if (!vid_shader) vid_shader = MakeShader("videovert.glsl", "videofrag.glsl");
if (!vid_shader) vid_shader = MakeShader("videovert.glsl", "videofrag.glsl");
newds->shader = vid_shader; newds->shader = vid_shader;
shader_use(newds->shader); shader_use(newds->shader);
glGenTextures(1, &newds->texture_y); glGenTextures(1, &newds->texture_y);
glBindTexture(GL_TEXTURE_2D, newds->texture_y); glBindTexture(GL_TEXTURE_2D, newds->texture_y);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
shader_setint(newds->shader, "texture_y", 0); shader_setint(newds->shader, "texture_y", 0);
glGenTextures(1, &newds->texture_cb); glGenTextures(1, &newds->texture_cb);
glBindTexture(GL_TEXTURE_2D, newds->texture_cb); glBindTexture(GL_TEXTURE_2D, newds->texture_cb);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
shader_setint(newds->shader, "texture_cb", 1); shader_setint(newds->shader, "texture_cb", 1);
glGenTextures(1, &newds->texture_cr); glGenTextures(1, &newds->texture_cr);
glBindTexture(GL_TEXTURE_2D, newds->texture_cr); glBindTexture(GL_TEXTURE_2D, newds->texture_cr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
shader_setint(newds->shader, "texture_cr", 2); shader_setint(newds->shader, "texture_cr", 2);
*/ */
return newds; return newds;
} }
void ds_advance(struct datastream *ds, double s) void ds_advance(struct datastream *ds, double s) {
{ if (ds->playing) {
if (ds->playing) { plm_decode(ds->plm, s);
plm_decode(ds->plm, s); }
}
} }
void ds_seek(struct datastream *ds, double time) void ds_seek(struct datastream *ds, double time) {
{ // clear_raw(ds->audio_device);
//clear_raw(ds->audio_device); plm_seek(ds->plm, time, false);
plm_seek(ds->plm, time, false);
} }
void ds_advanceframes(struct datastream *ds, int frames) void ds_advanceframes(struct datastream *ds, int frames) {
{ for (int i = 0; i < frames; i++) {
for (int i = 0; i < frames; i++) { plm_frame_t *frame = plm_decode_video(ds->plm);
plm_frame_t *frame = plm_decode_video(ds->plm); render_frame(ds->plm, frame, ds);
render_frame(ds->plm, frame, ds); }
}
} }
void ds_pause(struct datastream *ds) void ds_pause(struct datastream *ds) {
{ ds->playing = false;
ds->playing = false;
} }
void ds_stop(struct datastream *ds) void ds_stop(struct datastream *ds) {
{ if (ds->plm != NULL) {
if (ds->plm != NULL) { plm_destroy(ds->plm);
plm_destroy(ds->plm); ds->plm = NULL;
ds->plm = NULL; }
} if (ds->audio_device)
if (ds->audio_device) close_audio_device(ds->audio_device);
close_audio_device(ds->audio_device); ds->playing = false;
ds->playing = false;
} }
// TODO: Must be a better way // TODO: Must be a better way
int ds_videodone(struct datastream *ds) int ds_videodone(struct datastream *ds) {
{ return (ds->plm == NULL) || plm_get_time(ds->plm) >= plm_get_duration(ds->plm);
return (ds->plm == NULL)
|| plm_get_time(ds->plm) >= plm_get_duration(ds->plm);
} }
double ds_remainingtime(struct datastream *ds) double ds_remainingtime(struct datastream *ds) {
{ if (ds->plm != NULL)
if (ds->plm != NULL) return plm_get_duration(ds->plm) - plm_get_time(ds->plm);
return plm_get_duration(ds->plm) - plm_get_time(ds->plm); else
else return 0.f;
return 0.f;
} }
double ds_length(struct datastream *ds) double ds_length(struct datastream *ds) {
{ return plm_get_duration(ds->plm);
return plm_get_duration(ds->plm);
} }

View file

@ -1,21 +1,21 @@
#ifndef DATASTREAM_H #ifndef DATASTREAM_H
#define DATASTREAM_H #define DATASTREAM_H
#include <stdint.h>
#include <pl_mpeg.h> #include <pl_mpeg.h>
#include <stdint.h>
struct soundstream; struct soundstream;
struct datastream { struct datastream {
plm_t *plm; plm_t *plm;
struct shader *shader; struct shader *shader;
double last_time; double last_time;
int playing; int playing;
int audio_device; int audio_device;
uint32_t texture_y; uint32_t texture_y;
uint32_t texture_cb; uint32_t texture_cb;
uint32_t texture_cr; uint32_t texture_cr;
struct soundstream *astream; struct soundstream *astream;
}; };
struct Texture; struct Texture;
@ -24,7 +24,7 @@ extern struct shader *vid_shader;
struct datastream *MakeDatastream(); struct datastream *MakeDatastream();
void ds_openvideo(struct datastream *ds, const char *path, const char *adriver); void ds_openvideo(struct datastream *ds, const char *path, const char *adriver);
struct Texture *ds_maketexture(struct datastream*); struct Texture *ds_maketexture(struct datastream *);
void ds_advance(struct datastream *ds, double); void ds_advance(struct datastream *ds, double);
void ds_seek(struct datastream *ds, double); void ds_seek(struct datastream *ds, double);
void ds_advanceframes(struct datastream *ds, int frames); void ds_advanceframes(struct datastream *ds, int frames);

View file

@ -11,75 +11,163 @@
#include "stb_ds.h" #include "stb_ds.h"
#include "sokol/sokol_gfx.h" #include "sokol/sokol_gfx.h"
static uint32_t circleVBO; #include "font.h"
static uint32_t circleVAO;
static struct shader *circleShader;
static uint32_t gridVBO; static sg_pipeline grid_pipe;
static uint32_t gridVAO; static sg_bindings grid_bind;
static struct shader *gridShader; static sg_shader grid_shader;
static int grid_c = 0;
static uint32_t rectVBO; static sg_pipeline rect_pipe;
static uint32_t rectVAO; static sg_bindings rect_bind;
static struct shader *rectShader; static sg_shader rect_shader;
static int rect_c = 0;
typedef struct { static sg_pipeline circle_pipe;
float proj[16]; static sg_bindings circle_bind;
float res[2]; static sg_shader csg;
} circle_ubo; static int circle_count = 0;
static int circle_vert_c = 7;
void debug_flush() void debug_flush()
{ {
sg_apply_pipeline(circle_pipe);
sg_apply_bindings(&circle_bind);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
sg_draw(0,4,circle_count);
circle_count = 0;
sg_apply_pipeline(rect_pipe);
sg_apply_bindings(&rect_bind);
sg_apply_uniforms(SG_SHADERSTAGE_VS,0,SG_RANGE_REF(projection));
sg_draw(0,rect_c*2,1);
rect_c = 0;
} }
static sg_shader_uniform_block_desc projection_ubo = {
.size = sizeof(projection),
.uniforms = {
[0] = { .name = "proj", .type = SG_UNIFORMTYPE_MAT4 },
}
};
void debugdraw_init() void debugdraw_init()
{ {
sg_shader csg = sg_make_shader(&(sg_shader_desc){ csg = sg_make_shader(&(sg_shader_desc){
.vs.source = slurp_text("shaders/circlevert.glsl"), .vs.source = slurp_text("shaders/circlevert.glsl"),
.fs.source = slurp_text("shaders/circlefrag.glsl"), .fs.source = slurp_text("shaders/circlefrag.glsl"),
.vs.uniform_blocks[0] = { .vs.uniform_blocks[0] = projection_ubo,
.size = sizeof(circle_ubo),
.uniforms = {
[0] = { .name = "proj", .type = SG_UNIFORMTYPE_MAT4 },
[1] = { .name = "res", .type = SG_UNIFORMTYPE_FLOAT2 },
}
}
}); });
/*
float gridverts[] = {
-1.f, -1.f,
1.f, -1.f,
-1.f, 1.f,
1.f, 1.f
};
gridShader = MakeShader("gridvert.glsl", "gridfrag.glsl"); circle_pipe = sg_make_pipeline(&(sg_pipeline_desc){
shader_setUBO(gridShader, "Projection", 0); .shader = csg,
glGenBuffers(1, &gridVBO); .layout = {
glGenVertexArrays(1, &gridVAO); .attrs = {
glBindVertexArray(gridVAO); [0].format = SG_VERTEXFORMAT_FLOAT2,
glBindBuffer(GL_ARRAY_BUFFER, gridVBO); [0].buffer_index = 1,
glBufferData(GL_ARRAY_BUFFER, sizeof(gridverts), &gridverts, GL_STATIC_DRAW); [1].format = SG_VERTEXFORMAT_FLOAT3,
glEnableVertexAttribArray(0); [2].format = SG_VERTEXFORMAT_FLOAT2,
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); [3].format = SG_VERTEXFORMAT_FLOAT
},
.buffers[0].step_func = SG_VERTEXSTEP_PER_INSTANCE,
},
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
.cull_mode = SG_CULLMODE_BACK,
.colors[0].blend = {
.enabled = true,
.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA,
.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
.src_factor_alpha = SG_BLENDFACTOR_SRC_ALPHA,
.src_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA
},
.label = "circle pipeline"
});
rectShader = MakeShader("linevert.glsl", "linefrag.glsl"); circle_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
shader_setUBO(rectShader, "Projection", 0); .size = sizeof(float)*circle_vert_c*5000,
glGenBuffers(1, &rectVBO); .usage = SG_USAGE_STREAM,
glGenVertexArrays(1, &rectVAO); });
*/
float circleverts[8] = {
-1,-1,
-1,1,
1,-1,
1,1
};
circle_bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){
.data = SG_RANGE(circleverts),
.usage = SG_USAGE_IMMUTABLE,
});
grid_shader = sg_make_shader(&(sg_shader_desc){
.vs.source = slurp_text("shaders/gridvert.glsl"),
.fs.source = slurp_text("shaders/gridfrag.glsl"),
.vs.uniform_blocks[0] = projection_ubo,
.vs.uniform_blocks[1] = {
.size = sizeof(float)*2,
.uniforms = { [0] = { .name = "offset", .type = SG_UNIFORMTYPE_FLOAT2 } } },
.fs.uniform_blocks[0] = {
.size = sizeof(float)*5,
.uniforms = {
[0] = { .name = "thickness", .type = SG_UNIFORMTYPE_FLOAT },
[1] = { .name = "span", .type = SG_UNIFORMTYPE_FLOAT },
[2] = { .name = "color", .type = SG_UNIFORMTYPE_FLOAT3 },
}
},
});
grid_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = grid_shader,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT2
}
},
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
// .cull_mode = SG_CULLMODE_BACK,
.label = "grid pipeline",
.colors[0] = {
.blend = {
.enabled = true,
.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA,
.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
.op_rgb = SG_BLENDOP_ADD,
.src_factor_alpha = SG_BLENDFACTOR_SRC_ALPHA,
.dst_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
.op_alpha = SG_BLENDOP_ADD
},
},
});
grid_bind.vertex_buffers[0] = circle_bind.vertex_buffers[1];
rect_shader = sg_make_shader(&(sg_shader_desc){
.vs.source = slurp_text("shaders/linevert.glsl"),
.fs.source = slurp_text("shaders/linefrag.glsl"),
.vs.uniform_blocks[0] = projection_ubo
});
rect_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = rect_shader,
.layout = {
.attrs = { [0].format = SG_VERTEXFORMAT_FLOAT2 }
},
.primitive_type = SG_PRIMITIVETYPE_LINES
});
rect_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(float)*2*10000,
.usage = SG_USAGE_STREAM
});
} }
void draw_line(int x1, int y1, int x2, int y2, float *color) void draw_line(cpVect s, cpVect e, float *color)
{ {
shader_use(rectShader); cpVect verts[2] = {s, e};
float verts[] = { draw_poly(verts, 2, color);
x1, y1,
x2, y2
};
draw_poly(verts, 2, color);
} }
cpVect center_of_vects(cpVect *v, int n) cpVect center_of_vects(cpVect *v, int n)
@ -153,8 +241,8 @@ void draw_edge(cpVect *points, int n, struct color color, int thickness)
float col[3] = {(float)color.r/255, (float)color.g/255, (float)color.b/255}; float col[3] = {(float)color.r/255, (float)color.g/255, (float)color.b/255};
shader_use(rectShader); // shader_use(rectShader);
shader_setvec3(rectShader, "linecolor", col); // shader_setvec3(rectShader, "linecolor", col);
/* /*
if (thickness <= 1) { if (thickness <= 1) {
// glLineStipple(1, 0x00FF); // glLineStipple(1, 0x00FF);
@ -204,29 +292,16 @@ void draw_edge(cpVect *points, int n, struct color color, int thickness)
void draw_circle(int x, int y, float radius, int pixels, float *color, int fill) void draw_circle(int x, int y, float radius, int pixels, float *color, int fill)
{ {
/* shader_use(circleShader); float cv[circle_vert_c] = {0};
cv[0] = color[0];
float verts[] = { cv[1] = color[1];
x - radius, y - radius, -1, -1, cv[2] = color[2];
x + radius, y - radius, 1, -1, cv[3] = x;
x - radius, y + radius, -1, 1, cv[4] = y;
x + radius, y + radius, 1, 1 cv[5] = radius;
}; cv[6] = fill;
sg_append_buffer(circle_bind.vertex_buffers[0], SG_RANGE_REF(cv));
glBindBuffer(GL_ARRAY_BUFFER, circleVBO); circle_count++;
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_DYNAMIC_DRAW);
shader_setfloat(circleShader, "radius", radius);
shader_setint(circleShader, "thickness", pixels);
shader_setvec3(circleShader, "dbgColor", color);
shader_setbool(circleShader, "fill", fill);
shader_setfloat(circleShader, "zoom", cam_zoom());
glBindVertexArray(circleVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
*/
} }
void draw_rect(int x, int y, int w, int h, float *color) void draw_rect(int x, int y, int w, int h, float *color)
@ -234,13 +309,13 @@ void draw_rect(int x, int y, int w, int h, float *color)
float hw = w / 2.f; float hw = w / 2.f;
float hh = h / 2.f; float hh = h / 2.f;
float verts[] = { cpVect verts[4] = {
x - hw, y - hh, { .x = x-hw, .y = y-hh },
x + hw, y - hh, { .x = x+hw, .y = y-hh },
x + hw, y + hh, { .x = x+hw, .y = y+hh },
x - hw, y + hh { .x = x-hw, .y = y+hh }
}; };
draw_poly(verts, 4, color); draw_poly(verts, 4, color);
} }
@ -253,27 +328,33 @@ void draw_box(struct cpVect c, struct cpVect wh, struct color color)
void draw_arrow(struct cpVect start, struct cpVect end, struct color color, int capsize) void draw_arrow(struct cpVect start, struct cpVect end, struct color color, int capsize)
{ {
float col[3] = {(float)color.r/255, (float)color.g/255, (float)color.b/255}; float col[3] = {(float)color.r/255, (float)color.g/255, (float)color.b/255};
draw_line(start.x, start.y, end.x, end.y, col); draw_line(start, end, col);
draw_cppoint(end, capsize, color); draw_cppoint(end, capsize, color);
} }
void draw_grid(int width, int span) void draw_grid(int width, int span)
{ {
/* shader_use(gridShader);
shader_setint(gridShader, "thickness", width);
shader_setint(gridShader, "span", span);
cpVect offset = cam_pos(); cpVect offset = cam_pos();
offset = cpvmult(offset, 1/cam_zoom()); offset = cpvmult(offset, 1/cam_zoom());
offset.x -= mainwin->width/2; offset.x -= mainwin->width/2;
offset.y -= mainwin->height/2; offset.y -= mainwin->height/2;
shader_setvec2(gridShader, "offset", &offset); sg_apply_pipeline(grid_pipe);
sg_apply_bindings(&grid_bind);
glBindVertexArray(gridVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); float col[3] = { 0.3, 0.5, 0.8};
*/
float fubo[5];
fubo[0] = width;
fubo[1] = span;
fubo[2] = col;
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
sg_apply_uniforms(SG_SHADERSTAGE_VS, 1, SG_RANGE_REF(offset));
sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, SG_RANGE_REF(fubo));
sg_draw(0,4,1);
} }
void draw_point(int x, int y, float r, float *color) void draw_point(int x, int y, float r, float *color)
@ -293,8 +374,33 @@ void draw_points(struct cpVect *points, int n, float size, float *color)
draw_point(points[i].x, points[i].y, size, color); draw_point(points[i].x, points[i].y, size, color);
} }
void draw_poly(float *points, int n, float *color) void draw_poly(cpVect *points, int n, float *color)
{ {
if (n == 2) {
sg_range t;
t.ptr = points;
t.size = sizeof(cpVect)*2;
sg_append_buffer(rect_bind.vertex_buffers[0], &t);
rect_c += 1;
return;
} else if (n <= 1) return;
cpVect buffer[2*n];
for (int i = 0; i < n; i++) {
buffer[i*2] = points[i];
buffer[i*2+1] = points[i+1];
}
buffer[2*n-1] = points[0];
sg_range t;
t.ptr = buffer;
t.size = sizeof(cpVect)*2*n;
sg_append_buffer(rect_bind.vertex_buffers[0], &t);
rect_c += n;
/* shader_use(rectShader); /* shader_use(rectShader);
shader_setvec3(rectShader, "linecolor", color); shader_setvec3(rectShader, "linecolor", color);
glBindBuffer(GL_ARRAY_BUFFER, rectVBO); glBindBuffer(GL_ARRAY_BUFFER, rectVBO);
@ -312,17 +418,6 @@ void draw_poly(float *points, int n, float *color)
*/ */
} }
void draw_polyvec(cpVect *points, int n, float *color)
{
float drawvec[n*2];
for (int i = 0; i < n; i++) {
drawvec[i*2] = points[i].x;
drawvec[i*2+1] = points[i].y;
}
draw_poly(drawvec, n, color);
}
void debugdraw_flush() void debugdraw_flush()
{ {

View file

@ -5,7 +5,7 @@
struct color; struct color;
void debugdraw_init(); void debugdraw_init();
void draw_line(int x1, int y1, int x2, int y2, float *color); void draw_line(cpVect s, cpVect e, float *color);
void draw_edge(struct cpVect *points, int n, struct color color, int thickness); void draw_edge(struct cpVect *points, int n, struct color color, int thickness);
void draw_points(struct cpVect *points, int n, float size, float *color); void draw_points(struct cpVect *points, int n, float size, float *color);
void draw_arrow(struct cpVect start, struct cpVect end, struct color, int capsize); void draw_arrow(struct cpVect start, struct cpVect end, struct color, int capsize);
@ -15,7 +15,7 @@ void draw_rect(int x, int y, int w, int h, float *color);
void draw_box(struct cpVect c, struct cpVect wh, struct color color); void draw_box(struct cpVect c, struct cpVect wh, struct color color);
void draw_point(int x, int y, float r, float *color); void draw_point(int x, int y, float r, float *color);
void draw_cppoint(struct cpVect point, float r, struct color color); void draw_cppoint(struct cpVect point, float r, struct color color);
void draw_poly(float *points, int n, float *color); void draw_poly(cpVect *points, int n, float *color);
void debug_flush(); void debug_flush();

View file

@ -5,7 +5,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "resources.h" #include "resources.h"
#include "nuklear.h" #include "nuke.h"
#define ASSET_TYPE_NULL 0 #define ASSET_TYPE_NULL 0
#define ASSET_TYPE_IMAGE 1 #define ASSET_TYPE_IMAGE 1

View file

@ -16,54 +16,51 @@
#define PL_MPEG_IMPLEMENTATION #define PL_MPEG_IMPLEMENTATION
#include <pl_mpeg.h> #include <pl_mpeg.h>
#ifdef EDITOR #ifdef EDITOR
#include "editor.h" #include "editor.h"
#endif #endif
#include "render.h" #include "render.h"
#include "openglrender.h"
#include "window.h"
#include "camera.h"
#include "input.h"
#include "sprite.h"
#include "2dphysics.h" #include "2dphysics.h"
#include "camera.h"
#include "gameobject.h" #include "gameobject.h"
#include "input.h"
#include "log.h" #include "log.h"
#include "openglrender.h"
#include "resources.h" #include "resources.h"
#include "timer.h"
#include "script.h" #include "script.h"
#include "sprite.h"
#include "timer.h"
#include "window.h"
#include "sound.h" #include "sound.h"
#include "engine.h" #include "engine.h"
void error_callback(int error, const char *description) void error_callback(int error, const char *description) {
{ fprintf(stderr, "Error: %s\n", description);
fprintf(stderr, "Error: %s\n", description); YughError("GLFW Error: %s", description);
YughError("GLFW Error: %s", description);
} }
void engine_init() void engine_init() {
{ glfwSetErrorCallback(error_callback);
glfwSetErrorCallback(error_callback); /* Initialize GLFW */
/* Initialize GLFW */ if (!glfwInit()) {
if (!glfwInit()) { YughError("Could not init GLFW. Exiting.");
YughError("Could not init GLFW. Exiting."); exit(1);
exit(1); } else {
} else { YughInfo("Initted GLFW.");
YughInfo("Initted GLFW."); }
}
resources_init(); resources_init();
YughInfo("Starting physics ...");
phys2d_init();
YughInfo("Starting sound ...");
sound_init();
YughInfo("Starting scripts ..."); YughInfo("Starting physics ...");
script_init(); phys2d_init();
YughInfo("Starting sound ...");
sound_init();
YughInfo("Starting scripts ...");
script_init();
} }

File diff suppressed because it is too large Load diff

View file

@ -1,169 +1,153 @@
#include "font.h" #include "font.h"
#include "log.h"
#include "render.h" #include "render.h"
#include <shader.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h> #include <ctype.h>
#include <limits.h> #include <limits.h>
#include <shader.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <window.h> #include <window.h>
#include "log.h"
#include "openglrender.h" #include "openglrender.h"
#include "stb_truetype.h"
#include "stb_rect_pack.h"
#include "stb_image_write.h" #include "stb_image_write.h"
#include "stb_rect_pack.h"
#include "stb_truetype.h"
struct sFont *font; struct sFont *font;
static struct shader *shader;
static sg_shader fontshader;
unsigned char *slurp_file(const char *filename) { unsigned char *slurp_file(const char *filename) {
FILE *f = fopen(filename, "rb"); FILE *f = fopen(filename, "rb");
if (!f) return NULL; if (!f) return NULL;
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
long fsize = ftell(f); long fsize = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
unsigned char *slurp = malloc(fsize+1); unsigned char *slurp = malloc(fsize + 1);
fread(slurp,fsize,1,f); fread(slurp, fsize, 1, f);
fclose(f); fclose(f);
return slurp; return slurp;
} }
char *slurp_text(const char *filename) { char *slurp_text(const char *filename) {
FILE *f = fopen(filename, "r'"); FILE *f = fopen(filename, "r'");
if (!f) return NULL; if (!f) return NULL;
char *buf; char *buf;
long int fsize; long int fsize;
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
fsize = ftell(f); fsize = ftell(f);
buf = malloc(fsize+1); buf = malloc(fsize + 1);
rewind(f); rewind(f);
size_t r = fread(buf, sizeof(char), fsize, f); size_t r = fread(buf, sizeof(char), fsize, f);
buf[r] = '\0'; buf[r] = '\0';
fclose(f); fclose(f);
return buf; return buf;
} }
int slurp_write(const char *txt, const char *filename) int slurp_write(const char *txt, const char *filename) {
{ FILE *f = fopen(filename, "w");
FILE *f = fopen(filename, "w"); if (!f) return 1;
if (!f) return 1;
fputs(txt, f); fputs(txt, f);
fclose(f); fclose(f);
return 0; return 0;
} }
static sg_shader fontshader;
static sg_bindings bind_text; static sg_bindings bind_text;
static sg_pipeline pipe_text; static sg_pipeline pipe_text;
void font_init(struct shader *textshader) { static float text_buffer[16 * 40000];
shader = textshader; static uint16_t text_idx_buffer[6 * 40000];
static float color_buffer[3 * 40000];
fontshader = sg_make_shader(&(sg_shader_desc){ void font_init(struct shader *textshader) {
fontshader = sg_make_shader(&(sg_shader_desc){
.vs.source = slurp_text("shaders/textvert.glsl"), .vs.source = slurp_text("shaders/textvert.glsl"),
.fs.source = slurp_text("shaders/textfrag.glsl"), .fs.source = slurp_text("shaders/textfrag.glsl"),
.vs.uniform_blocks[0] = { .vs.uniform_blocks[0] = {
.size = sizeof(float)*16, .size = sizeof(float) * 16,
// .layout = SG_UNIFORMLAYOUT_STD140, // .layout = SG_UNIFORMLAYOUT_STD140,
.uniforms = { .uniforms = {
[0] = { .name = "projection", .type = SG_UNIFORMTYPE_MAT4 } [0] = {.name = "projection", .type = SG_UNIFORMTYPE_MAT4}}},
}
},
.fs.images[0] = { .fs.images[0] = {.name = "text", .image_type = SG_IMAGETYPE_2D, .sampler_type = SG_SAMPLERTYPE_FLOAT}});
.name = "text",
.image_type = SG_IMAGETYPE_2D,
.sampler_type = SG_SAMPLERTYPE_FLOAT
}
});
pipe_text = sg_make_pipeline(&(sg_pipeline_desc){ pipe_text = sg_make_pipeline(&(sg_pipeline_desc){
.shader = fontshader, .shader = fontshader,
.layout = { .layout = {
.attrs = { .attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT2, [0].format = SG_VERTEXFORMAT_FLOAT2,
[0].buffer_index = 0, [0].buffer_index = 0,
[1].format = SG_VERTEXFORMAT_FLOAT2, [1].format = SG_VERTEXFORMAT_FLOAT2,
[1].buffer_index = 0, [1].buffer_index = 0,
[2].format = SG_VERTEXFORMAT_FLOAT3, [2].format = SG_VERTEXFORMAT_FLOAT3,
[2].buffer_index = 1}, [2].buffer_index = 1,
.buffers[2].step_func = SG_VERTEXSTEP_PER_INSTANCE, },
}, },
// .primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
.label = "text pipeline", .label = "text pipeline",
.index_type = SG_INDEXTYPE_UINT16 .index_type = SG_INDEXTYPE_UINT16});
});
bind_text.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ bind_text.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(float)*16*500, .size = sizeof(float) * 16 * 40000,
.type = SG_BUFFERTYPE_VERTEXBUFFER, .type = SG_BUFFERTYPE_VERTEXBUFFER,
.usage = SG_USAGE_STREAM, .usage = SG_USAGE_STREAM,
.label = "text buffer" .label = "text buffer"});
});
bind_text.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){
bind_text.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){ .size = sizeof(float) * 3 * 4 * 40000,
.size = sizeof(float)*3*40000,
.type = SG_BUFFERTYPE_VERTEXBUFFER, .type = SG_BUFFERTYPE_VERTEXBUFFER,
.usage = SG_USAGE_STREAM, .usage = SG_USAGE_STREAM,
.label = "text color buffer" .label = "text color buffer"});
});
bind_text.index_buffer = sg_make_buffer(&(sg_buffer_desc){
bind_text.index_buffer = sg_make_buffer(&(sg_buffer_desc){ .size = sizeof(uint16_t) * 6 * 40000,
.size = sizeof(uint16_t)*6*500,
.type = SG_BUFFERTYPE_INDEXBUFFER, .type = SG_BUFFERTYPE_INDEXBUFFER,
.usage = SG_USAGE_STREAM, .usage = SG_USAGE_STREAM,
.label = "text index buffer" .label = "text index buffer"});
});
font = MakeFont("LessPerfectDOSVGA.ttf", 16);
font = MakeFont("LessPerfectDOSVGA.ttf", 16); bind_text.fs_images[0] = font->texID;
bind_text.fs_images[0] = font->texID;
} }
void font_frame(struct window *w) { struct sFont *MakeFont(const char *fontfile, int height) {
shader_use(shader); YughInfo("Making font %s.", fontfile);
}
struct sFont *MakeFont(const char *fontfile, int height) int packsize = 1024;
{
YughInfo("Making font %s.", fontfile);
int packsize = 128; struct sFont *newfont = calloc(1, sizeof(struct sFont));
newfont->height = height;
struct sFont *newfont = calloc(1, sizeof(struct sFont)); char fontpath[256];
newfont->height = height; snprintf(fontpath, 256, "fonts/%s", fontfile);
char fontpath[256]; unsigned char *ttf_buffer = slurp_file(fontpath);
snprintf(fontpath, 256, "fonts/%s", fontfile); unsigned char *bitmap = malloc(packsize * packsize);
unsigned char *ttf_buffer = slurp_file(fontpath); stbtt_packedchar glyphs[95];
unsigned char *bitmap = malloc(packsize*packsize);
stbtt_packedchar glyphs[95]; stbtt_pack_context pc;
stbtt_pack_context pc; stbtt_PackBegin(&pc, bitmap, packsize, packsize, 0, 1, NULL);
stbtt_PackFontRange(&pc, ttf_buffer, 0, height, 32, 95, glyphs);
stbtt_PackEnd(&pc);
stbtt_PackBegin(&pc, bitmap, packsize, packsize, 0, 1, NULL); stbi_write_png("packedfont.png", packsize, packsize, 1, bitmap, sizeof(char) * packsize);
stbtt_PackFontRange(&pc, ttf_buffer, 0, height, 32, 95, glyphs);
stbtt_PackEnd(&pc);
stbi_write_png("packedfont.png", packsize, packsize, 1, bitmap, sizeof(char) * packsize); stbtt_fontinfo fontinfo;
if (!stbtt_InitFont(&fontinfo, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer, 0))) {
YughError("Failed to make font %s", fontfile);
}
stbtt_fontinfo fontinfo; newfont->texID = sg_make_image(&(sg_image_desc){
if (!stbtt_InitFont(&fontinfo, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0))) {
YughError("Failed to make font %s", fontfile);
}
newfont->texID = sg_make_image(&(sg_image_desc){
.type = SG_IMAGETYPE_2D, .type = SG_IMAGETYPE_2D,
.width = packsize, .width = packsize,
.height = packsize, .height = packsize,
@ -172,215 +156,201 @@ struct sFont *MakeFont(const char *fontfile, int height)
.min_filter = SG_FILTER_NEAREST, .min_filter = SG_FILTER_NEAREST,
.mag_filter = SG_FILTER_NEAREST, .mag_filter = SG_FILTER_NEAREST,
.data.subimage[0][0] = { .data.subimage[0][0] = {
.ptr = bitmap, .ptr = bitmap,
.size = packsize*packsize .size = packsize * packsize}});
}
});
free(ttf_buffer); free(ttf_buffer);
free(bitmap); free(bitmap);
for (unsigned char c = 32; c < 127; c++) { for (unsigned char c = 32; c < 127; c++) {
stbtt_packedchar glyph = glyphs[c-32]; stbtt_packedchar glyph = glyphs[c - 32];
struct glrect r; struct glrect r;
r.s0 = glyph.x0 / (float) packsize; r.s0 = glyph.x0 / (float)packsize;
r.s1 = glyph.x1 / (float) packsize; r.s1 = glyph.x1 / (float)packsize;
r.t0 = glyph.y0 / (float) packsize; r.t0 = glyph.y0 / (float)packsize;
r.t1 = glyph.y1 / (float) packsize; r.t1 = glyph.y1 / (float)packsize;
newfont->Characters[c].Advance = glyph.xadvance; newfont->Characters[c].Advance = glyph.xadvance;
newfont->Characters[c].Size[0] = glyph.x1 - glyph.x0; newfont->Characters[c].Size[0] = glyph.x1 - glyph.x0;
newfont->Characters[c].Size[1] = glyph.y1 - glyph.y0; newfont->Characters[c].Size[1] = glyph.y1 - glyph.y0;
newfont->Characters[c].Bearing[0] = glyph.xoff; newfont->Characters[c].Bearing[0] = glyph.xoff;
newfont->Characters[c].Bearing[1] = glyph.yoff2; newfont->Characters[c].Bearing[1] = glyph.yoff2;
newfont->Characters[c].rect = r; newfont->Characters[c].rect = r;
} }
return newfont; return newfont;
} }
static int curchar = 0; static int curchar = 0;
void draw_char_box(struct Character c, float cursor[2], float scale, float color[3]) void draw_char_box(struct Character c, float cursor[2], float scale, float color[3]) {
{
int x, y, w, h; int x, y, w, h;
x = cursor[0]; x = cursor[0];
y = cursor[1]; y = cursor[1];
w = 8*scale; w = 8 * scale;
h = 14; h = 14;
x += w/2.f; x += w / 2.f;
y += h/2.f; y += h / 2.f;
draw_rect(x,y,w,h,color); draw_rect(x, y, w, h, color);
} }
void text_flush() void text_flush() {
{ if (curchar == 0) return;
sg_apply_pipeline(pipe_text); sg_apply_pipeline(pipe_text);
sg_apply_bindings(&bind_text); sg_apply_bindings(&bind_text);
sg_apply_uniforms(SG_SHADERSTAGE_VS,0,SG_RANGE_REF(projection)); sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
sg_range verts;
verts.ptr = text_buffer;
verts.size = sizeof(float) * 16 * curchar;
sg_update_buffer(bind_text.vertex_buffers[0], &verts);
sg_draw(0,6*curchar,1); sg_range idxs;
idxs.ptr = text_idx_buffer;
idxs.size = sizeof(uint16_t) * 6 * curchar;
sg_update_buffer(bind_text.index_buffer, &idxs);
sg_range c = {
.ptr = color_buffer,
.size = sizeof(float) * 3 * 4 * curchar};
sg_update_buffer(bind_text.vertex_buffers[1], &c);
sg_draw(0, 6 * curchar, 1);
curchar = 0; curchar = 0;
} }
void fill_charverts(float *verts, float cursor[2], float scale, struct Character c, float *offset) void fill_charverts(float *verts, float cursor[2], float scale, struct Character c, float *offset) {
{
float w = c.Size[0] * scale; float w = c.Size[0] * scale;
float h = c.Size[1] * scale; float h = c.Size[1] * scale;
float xpos = cursor[0] + (c.Bearing[0]+offset[0]) * scale; float xpos = cursor[0] + (c.Bearing[0] + offset[0]) * scale;
float ypos = cursor[1] - (c.Bearing[1]+offset[1]) * scale; float ypos = cursor[1] - (c.Bearing[1] + offset[1]) * scale;
float v[16] = { float v[16] = {
xpos, ypos, c.rect.s0, c.rect.t1, xpos, ypos, c.rect.s0, c.rect.t1,
xpos+w, ypos, c.rect.s1, c.rect.t1, xpos + w, ypos, c.rect.s1, c.rect.t1,
xpos, ypos + h, c.rect.s0, c.rect.t0, xpos, ypos + h, c.rect.s0, c.rect.t0,
xpos + w, ypos + h, c.rect.s1, c.rect.t0 xpos + w, ypos + h, c.rect.s1, c.rect.t0};
};
memcpy(verts, v, sizeof(float) * 16);
memcpy(verts, v, sizeof(float)*16);
} }
static int drawcaret = 0; static int drawcaret = 0;
void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, struct shader *shader, float color[3]) void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, float color[3]) {
{ float shadowcolor[3] = {0.f, 0.f, 0.f};
float shadowcolor[3] = {0.f, 0.f, 0.f}; float shadowcursor[2];
float shadowcursor[2];
float verts[16];
float verts[16]; float offset[2] = {-1, 1};
float offset[2] = {-1, 1};
fill_charverts(verts, cursor, scale, c, offset);
fill_charverts(verts, cursor, scale, c, offset);
/* Check if the vertex is off screen */
/* Check if the vertex is off screen */ if (verts[5] < -window_i(0)->width / 2.f || verts[9] < -window_i(0)->height / 2.f || verts[0] > window_i(0)->width / 2.f || verts[1] > window_i(0)->height / 2.f)
if (verts[5] < 0 || verts[10] < 0 || verts[0] > window_i(0)->width || verts[1] > window_i(0)->height)
return;
curchar++;
/* SET COLOR ? */
uint16_t pts[6] = {
0, 1, 2,
2, 1, 3
};
for (int i = 0; i < 6; i++) pts[i] += curchar*4;
sg_append_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
sg_append_buffer(bind_text.vertex_buffers[1], SG_RANGE_REF(color));
sg_append_buffer(bind_text.index_buffer, SG_RANGE_REF(pts));
return; return;
// fill_charverts(verts, cursor, scale, c, offset); uint16_t pts[6] = {
0, 1, 2,
2, 1, 3};
/* for (int i = 0; i < 6; i++)
if (drawcaret == curchar) { pts[i] += curchar * 4;
draw_char_box(c, cursor, scale, color);
shader_use(shader);
shader_setvec3(shader, "textColor", color);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, font->texID);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
}
*/
// sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, SG_RANGE_REF(shadowcolor));
/*
sg_append_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
offset[0] = 1;
offset[1] = -1;
fill_charverts(verts, cursor, scale, c, offset);
sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
offset[1] = 1;
fill_charverts(verts, cursor, scale, c, offset);
sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
offset[0] = -1;
offset[1] = -1;
fill_charverts(verts, cursor, scale, c, offset);
sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
*/
offset[0] = offset[1] = 0;
fill_charverts(verts, cursor, scale, c, offset);
/* SET COLOR ? */
sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
}
void text_settype(struct sFont *mfont) memcpy(text_buffer + (16 * curchar), verts, sizeof(verts));
{ for (int i = 0; i < 4; i++)
font = mfont; memcpy(color_buffer + (12 * curchar) + (3 * i), color, sizeof(color));
} memcpy(text_idx_buffer + (6 * curchar), pts, sizeof(pts));
curchar++;
return;
int renderText(const char *text, mfloat_t pos[2], float scale, mfloat_t color[3], float lw, int caret) /*
{ if (drawcaret == curchar) {
int len = strlen(text); draw_char_box(c, cursor, scale, color);
drawcaret = caret; shader_use(shader);
mfloat_t cursor[2] = { 0.f };
cursor[0] = pos[0];
cursor[1] = pos[1];
const unsigned char *line, *wordstart, *drawstart;
line = drawstart = (unsigned char*)text;
float *usecolor = color;
while (*line != '\0') {
switch (*line) {
case '\n':
sdrawCharacter(font->Characters[*line], cursor, scale, shader, usecolor);
cursor[1] -= scale * font->height;
cursor[0] = pos[0];
line++;
break;
case ' ':
sdrawCharacter(font->Characters[*line], cursor, scale, shader, usecolor);
cursor[0] += font->Characters[*line].Advance * scale;
line++;
break;
case '\t':
sdrawCharacter(font->Characters[*line], cursor, scale, shader, usecolor);
cursor[0] += font->Characters[*line].Advance * scale;
line++;
break;
default:
wordstart = line;
int wordWidth = 0;
while (!isspace(*line) && *line != '\0') {
wordWidth += font->Characters[*line].Advance * scale;
line++;
}
if (lw > 0 && (cursor[0] + wordWidth - pos[0]) >= lw) {
cursor[0] = pos[0];
cursor[1] -= scale * font->height;
}
while (wordstart < line) {
sdrawCharacter(font->Characters[*wordstart], cursor, scale, shader, usecolor);
cursor[0] += font->Characters[*wordstart].Advance * scale;
wordstart++;
}
} }
} */
/*
sg_append_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
/* if (caret > curchar) { offset[0] = 1;
draw_char_box(font->Characters[69], cursor, scale, color); offset[1] = -1;
} fill_charverts(verts, cursor, scale, c, offset);
*/ sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
offset[1] = 1;
fill_charverts(verts, cursor, scale, c, offset);
sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
offset[0] = -1;
offset[1] = -1;
fill_charverts(verts, cursor, scale, c, offset);
sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
*/
offset[0] = offset[1] = 0;
fill_charverts(verts, cursor, scale, c, offset);
sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts));
}
void text_settype(struct sFont *mfont) {
font = mfont;
}
int renderText(const char *text, mfloat_t pos[2], float scale, mfloat_t color[3], float lw, int caret) {
int len = strlen(text);
drawcaret = caret;
mfloat_t cursor[2] = {0.f};
cursor[0] = pos[0];
cursor[1] = pos[1];
const unsigned char *line, *wordstart, *drawstart;
line = drawstart = (unsigned char *)text;
float *usecolor = color;
while (*line != '\0') {
if (isblank(*line)) {
sdrawCharacter(font->Characters[*line], cursor, scale, usecolor);
cursor[0] += font->Characters[*line].Advance * scale;
line++;
} else if (isspace(*line)) {
sdrawCharacter(font->Characters[*line], cursor, scale, usecolor);
cursor[1] -= scale * font->height;
cursor[0] = pos[0];
line++;
} else {
wordstart = line;
int wordWidth = 0;
while (!isspace(*line) && *line != '\0') {
wordWidth += font->Characters[*line].Advance * scale;
line++;
}
if (lw > 0 && (cursor[0] + wordWidth - pos[0]) >= lw) {
cursor[0] = pos[0];
cursor[1] -= scale * font->height;
}
while (wordstart < line) {
sdrawCharacter(font->Characters[*wordstart], cursor, scale, usecolor);
cursor[0] += font->Characters[*wordstart].Advance * scale;
wordstart++;
}
}
}
/* if (caret > curchar) {
draw_char_box(font->Characters[69], cursor, scale, color);
}
*/
return cursor[1] - pos[1]; return cursor[1] - pos[1];
} }

View file

@ -2,36 +2,34 @@
#define FONT_H #define FONT_H
#include "mathc.h" #include "mathc.h"
#include "texture.h"
#include "sokol/sokol_gfx.h" #include "sokol/sokol_gfx.h"
#include "texture.h"
struct shader; struct shader;
struct window; struct window;
/// Holds all state information relevant to a character as loaded using FreeType /// Holds all state information relevant to a character as loaded using FreeType
struct Character { struct Character {
mfloat_t Size[2]; // Size of glyph mfloat_t Size[2]; // Size of glyph
mfloat_t Bearing[2]; // Offset from baseline to left/top of glyph mfloat_t Bearing[2]; // Offset from baseline to left/top of glyph
unsigned int Advance; // Horizontal offset to advance to next glyph unsigned int Advance; // Horizontal offset to advance to next glyph
struct glrect rect; struct glrect rect;
}; };
struct sFont { struct sFont {
uint32_t fontTexture; uint32_t fontTexture;
uint32_t height; uint32_t height;
struct Character Characters[127]; struct Character Characters[127];
sg_image texID; sg_image texID;
}; };
void font_init(struct shader *s); void font_init(struct shader *s);
void font_frame(struct window *w);
struct sFont *MakeFont(const char *fontfile, int height); struct sFont *MakeFont(const char *fontfile, int height);
void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, struct shader *shader, float color[3]); void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, float color[3]);
void text_settype(struct sFont *font); void text_settype(struct sFont *font);
int renderText(const char *text, mfloat_t pos[2], float scale, mfloat_t color[3], float lw,int caret); int renderText(const char *text, mfloat_t pos[2], float scale, mfloat_t color[3], float lw, int caret);
//void text_frame(); // void text_frame();
void text_flush(); void text_flush();
unsigned char *slurp_file(const char *filename); unsigned char *slurp_file(const char *filename);

View file

@ -1,61 +1,56 @@
#include "gameobject.h" #include "gameobject.h"
#include "2dphysics.h"
#include "debugdraw.h"
#include "input.h"
#include "log.h"
#include "nuke.h"
#include "resources.h"
#include "script.h"
#include "shader.h" #include "shader.h"
#include "sprite.h" #include "sprite.h"
#include "2dphysics.h"
#include "script.h"
#include "input.h"
#include <string.h>
#include <chipmunk/chipmunk.h> #include <chipmunk/chipmunk.h>
#include "resources.h" #include <string.h>
#include "nuke.h"
#include "log.h"
#include "debugdraw.h"
#include "stb_ds.h" #include "stb_ds.h"
struct gameobject *gameobjects = NULL; struct gameobject *gameobjects = NULL;
static int first = -1; static int first = -1;
const int nameBuf[MAXNAME] = { 0 }; const int nameBuf[MAXNAME] = {0};
const int prefabNameBuf[MAXNAME] = { 0 }; const int prefabNameBuf[MAXNAME] = {0};
struct gameobject *get_gameobject_from_id(int id) struct gameobject *get_gameobject_from_id(int id) {
{ if (id < 0) return NULL; if (id < 0) return NULL;
return &gameobjects[id]; return &gameobjects[id];
} }
struct gameobject *id2go(int id) struct gameobject *id2go(int id) {
{ if (id < 0) return NULL;
if (id < 0) return NULL;
return &gameobjects[id]; return &gameobjects[id];
} }
int body2id(cpBody *body) int body2id(cpBody *body) {
{
return (int)cpBodyGetUserData(body); return (int)cpBodyGetUserData(body);
} }
cpBody *id2body(int id) cpBody *id2body(int id) {
{
struct gameobject *go = id2go(id); struct gameobject *go = id2go(id);
if (go) if (go)
return go->body; return go->body;
return NULL; return NULL;
} }
int shape2gameobject(cpShape *shape) int shape2gameobject(cpShape *shape) {
{
struct phys2d_shape *s = cpShapeGetUserData(shape); struct phys2d_shape *s = cpShapeGetUserData(shape);
return s->go; return s->go;
} }
int pos2gameobject(cpVect pos) int pos2gameobject(cpVect pos) {
{
cpShape *hit = phys2d_query_pos(pos); cpShape *hit = phys2d_query_pos(pos);
if (hit) { if (hit) {
@ -73,269 +68,255 @@ int pos2gameobject(cpVect pos)
} }
int id_from_gameobject(struct gameobject *go) { int id_from_gameobject(struct gameobject *go) {
for (int i = 0; i < arrlen(gameobjects); i++) { for (int i = 0; i < arrlen(gameobjects); i++) {
if (&gameobjects[i] == go) return i; if (&gameobjects[i] == go) return i;
} }
return -1; return -1;
} }
void gameobject_set_sensor(int id, int sensor) void gameobject_set_sensor(int id, int sensor) {
{
id2go(id)->sensor = sensor; id2go(id)->sensor = sensor;
gameobject_apply(id2go(id)); gameobject_apply(id2go(id));
} }
int go2id(struct gameobject *go) int go2id(struct gameobject *go) {
{
return id_from_gameobject(go); return id_from_gameobject(go);
} }
void go_shape_apply(cpBody *body, cpShape *shape, struct gameobject *go) void go_shape_apply(cpBody *body, cpShape *shape, struct gameobject *go) {
{ cpShapeSetFriction(shape, go->f);
cpShapeSetFriction(shape, go->f); cpShapeSetElasticity(shape, go->e);
cpShapeSetElasticity(shape, go->e); cpShapeSetCollisionType(shape, go2id(go));
cpShapeSetCollisionType(shape, go2id(go));
/* cpShapeFilter filter; /* cpShapeFilter filter;
filter.group = go2id(go); filter.group = go2id(go);
filter.categories = 1<<go->layer; filter.categories = 1<<go->layer;
filter.mask = category_masks[go->layer]; filter.mask = category_masks[go->layer];
cpShapeSetFilter(shape, filter); cpShapeSetFilter(shape, filter);
*/ */
} }
void go_shape_moi(cpBody *body, cpShape *shape, struct gameobject *go) void go_shape_moi(cpBody *body, cpShape *shape, struct gameobject *go) {
{ float moment = cpBodyGetMoment(go->body);
float moment = cpBodyGetMoment(go->body); struct phys2d_shape *s = cpShapeGetUserData(shape);
struct phys2d_shape *s = cpShapeGetUserData(shape); if (!s) {
if (!s) { cpBodySetMoment(go->body, moment + 1);
cpBodySetMoment(go->body, moment+1); return;
return; }
}
moment += s->moi(s->data, go->mass);
moment += s->moi(s->data, go->mass); cpBodySetMoment(go->body, moment);
cpBodySetMoment(go->body, moment);
} }
void gameobject_apply(struct gameobject *go) void gameobject_apply(struct gameobject *go) {
{ cpBodySetType(go->body, go->bodytype);
cpBodySetType(go->body, go->bodytype); cpBodyEachShape(go->body, go_shape_apply, go);
cpBodyEachShape(go->body, go_shape_apply, go);
if (go->bodytype == CP_BODY_TYPE_DYNAMIC) {
if (go->bodytype == CP_BODY_TYPE_DYNAMIC) { cpBodySetMass(go->body, go->mass);
cpBodySetMass(go->body, go->mass); cpBodySetMoment(go->body, 0.f);
cpBodySetMoment(go->body, 0.f); cpBodyEachShape(go->body, go_shape_moi, go);
cpBodyEachShape(go->body, go_shape_moi, go);
if (cpBodyGetMoment(go->body) <= 0.f)
if (cpBodyGetMoment(go->body) <= 0.f) cpBodySetMoment(go->body, 1.f);
cpBodySetMoment(go->body, 1.f);
return;
return; }
}
} }
static void gameobject_setpickcolor(struct gameobject *go) static void gameobject_setpickcolor(struct gameobject *go) {
{ /*
/* float r = ((go->editor.id & 0x000000FF) >> 0) / 255.f;
float r = ((go->editor.id & 0x000000FF) >> 0) / 255.f; float g = ((go->editor.id & 0x0000FF00) >> 8) / 255.f;
float g = ((go->editor.id & 0x0000FF00) >> 8) / 255.f; float b = ((go->editor.id & 0x00FF0000) >> 16) / 255.f;
float b = ((go->editor.id & 0x00FF0000) >> 16) / 255.f;
go->editor.color[0] = r; go->editor.color[0] = r;
go->editor.color[1] = g; go->editor.color[1] = g;
go->editor.color[2] = b; go->editor.color[2] = b;
*/ */
} }
int MakeGameobject() int MakeGameobject() {
{ struct gameobject go = {
struct gameobject go = { .scale = 1.f,
.scale = 1.f, .bodytype = CP_BODY_TYPE_STATIC,
.bodytype = CP_BODY_TYPE_STATIC, .mass = 1.f,
.mass = 1.f, .next = -1,
.next = -1, .sensor = 0,
.sensor = 0, .shape_cbs = NULL,
.shape_cbs = NULL, };
};
go.cbs.begin.obj = JS_NULL; go.cbs.begin.obj = JS_NULL;
go.cbs.separate.obj = JS_NULL; go.cbs.separate.obj = JS_NULL;
go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f)); go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f));
int retid; int retid;
if (first<0) { if (first < 0) {
arrput(gameobjects, go); arrput(gameobjects, go);
retid = arrlast(gameobjects).id = arrlen(gameobjects)-1; retid = arrlast(gameobjects).id = arrlen(gameobjects) - 1;
} else { } else {
retid = first; retid = first;
first = id2go(first)->next; first = id2go(first)->next;
*id2go(retid) = go; *id2go(retid) = go;
} }
cpBodySetUserData(go.body, (void*)retid); cpBodySetUserData(go.body, (void *)retid);
phys2d_setup_handlers(retid); phys2d_setup_handlers(retid);
return retid; return retid;
} }
void rm_body_shapes(cpBody *body, cpShape *shape, void *data) { void rm_body_shapes(cpBody *body, cpShape *shape, void *data) {
struct phys2d_shape *s = cpShapeGetUserData(shape); struct phys2d_shape *s = cpShapeGetUserData(shape);
if (s->data) { if (s->data) {
free(s->data); free(s->data);
s->data = NULL; s->data = NULL;
} }
cpSpaceRemoveShape(space, shape); cpSpaceRemoveShape(space, shape);
cpShapeFree(shape); cpShapeFree(shape);
} }
int *go_toclean = NULL; int *go_toclean = NULL;
/* Free this gameobject */ /* Free this gameobject */
void gameobject_clean(int id) { void gameobject_clean(int id) {
struct gameobject *go = id2go(id); struct gameobject *go = id2go(id);
arrfree(go->shape_cbs); arrfree(go->shape_cbs);
cpBodyEachShape(go->body, rm_body_shapes, NULL); cpBodyEachShape(go->body, rm_body_shapes, NULL);
cpSpaceRemoveBody(space, go->body); cpSpaceRemoveBody(space, go->body);
cpBodyFree(go->body); cpBodyFree(go->body);
go->body = NULL; go->body = NULL;
} }
/* Really more of a "mark for deletion" ... */ /* Really more of a "mark for deletion" ... */
void gameobject_delete(int id) void gameobject_delete(int id) {
{ id2go(id)->next = first;
id2go(id)->next = first; first = id;
first = id;
if (cpSpaceIsLocked(space)) if (cpSpaceIsLocked(space))
arrpush(go_toclean, id); arrpush(go_toclean, id);
else else
gameobject_clean(id); gameobject_clean(id);
} }
void gameobjects_cleanup() { void gameobjects_cleanup() {
for (int i = 0; i < arrlen(go_toclean); i++) for (int i = 0; i < arrlen(go_toclean); i++)
gameobject_clean(go_toclean[i]); gameobject_clean(go_toclean[i]);
arrsetlen(go_toclean, 0); arrsetlen(go_toclean, 0);
return;
int clean = first; return;
while (clean >= 0 && id2go(clean)->body) { int clean = first;
gameobject_clean(clean);
clean = id2go(clean)->next; while (clean >= 0 && id2go(clean)->body) {
} gameobject_clean(clean);
clean = id2go(clean)->next;
}
} }
void gameobject_move(struct gameobject *go, cpVect vec) void gameobject_move(struct gameobject *go, cpVect vec) {
{ cpVect p = cpBodyGetPosition(go->body);
cpVect p = cpBodyGetPosition(go->body); p.x += vec.x;
p.x += vec.x; p.y += vec.y;
p.y += vec.y; cpBodySetPosition(go->body, p);
cpBodySetPosition(go->body, p);
phys2d_reindex_body(go->body); phys2d_reindex_body(go->body);
} }
void gameobject_rotate(struct gameobject *go, float as) void gameobject_rotate(struct gameobject *go, float as) {
{ cpFloat a = cpBodyGetAngle(go->body);
cpFloat a = cpBodyGetAngle(go->body); a += as * deltaT;
a += as * deltaT; cpBodySetAngle(go->body, a);
cpBodySetAngle(go->body, a);
phys2d_reindex_body(go->body); phys2d_reindex_body(go->body);
} }
void gameobject_setangle(struct gameobject *go, float angle) { void gameobject_setangle(struct gameobject *go, float angle) {
cpBodySetAngle(go->body, angle); cpBodySetAngle(go->body, angle);
phys2d_reindex_body(go->body); phys2d_reindex_body(go->body);
} }
void gameobject_setpos(struct gameobject *go, cpVect vec) { void gameobject_setpos(struct gameobject *go, cpVect vec) {
if (!go || !go->body) return; if (!go || !go->body) return;
cpBodySetPosition(go->body, vec); cpBodySetPosition(go->body, vec);
phys2d_reindex_body(go->body); phys2d_reindex_body(go->body);
} }
void object_gui(struct gameobject *go) void object_gui(struct gameobject *go) {
{ /*
/* float temp_pos[2];
float temp_pos[2]; temp_pos[0] = cpBodyGetPosition(go->body).x;
temp_pos[0] = cpBodyGetPosition(go->body).x; temp_pos[1] = cpBodyGetPosition(go->body).y;
temp_pos[1] = cpBodyGetPosition(go->body).y;
draw_point(temp_pos[0], temp_pos[1], 3); draw_point(temp_pos[0], temp_pos[1], 3);
nuke_property_float2("Position", -1000000.f, temp_pos, 1000000.f, 1.f, 0.5f); nuke_property_float2("Position", -1000000.f, temp_pos, 1000000.f, 1.f, 0.5f);
cpVect tvect = { temp_pos[0], temp_pos[1] }; cpVect tvect = { temp_pos[0], temp_pos[1] };
cpBodySetPosition(go->body, tvect); cpBodySetPosition(go->body, tvect);
float mtry = cpBodyGetAngle(go->body); float mtry = cpBodyGetAngle(go->body);
float modtry = fmodf(mtry * RAD2DEGS, 360.f); float modtry = fmodf(mtry * RAD2DEGS, 360.f);
if (modtry < 0.f) if (modtry < 0.f)
modtry += 360.f; modtry += 360.f;
float modtry2 = modtry; float modtry2 = modtry;
nuke_property_float("Angle", -1000.f, &modtry, 1000.f, 0.5f, 0.5f); nuke_property_float("Angle", -1000.f, &modtry, 1000.f, 0.5f, 0.5f);
modtry -= modtry2; modtry -= modtry2;
cpBodySetAngle(go->body, mtry + (modtry * DEG2RADS)); cpBodySetAngle(go->body, mtry + (modtry * DEG2RADS));
nuke_property_float("Scale", 0.f, &go->scale, 1000.f, 0.01f, go->scale * 0.01f); nuke_property_float("Scale", 0.f, &go->scale, 1000.f, 0.01f, go->scale * 0.01f);
nuke_nel(3); nuke_nel(3);
nuke_radio_btn("Static", &go->bodytype, CP_BODY_TYPE_STATIC); nuke_radio_btn("Static", &go->bodytype, CP_BODY_TYPE_STATIC);
nuke_radio_btn("Dynamic", &go->bodytype, CP_BODY_TYPE_DYNAMIC); nuke_radio_btn("Dynamic", &go->bodytype, CP_BODY_TYPE_DYNAMIC);
nuke_radio_btn("Kinematic", &go->bodytype, CP_BODY_TYPE_KINEMATIC); nuke_radio_btn("Kinematic", &go->bodytype, CP_BODY_TYPE_KINEMATIC);
cpBodySetType(go->body, go->bodytype); cpBodySetType(go->body, go->bodytype);
if (go->bodytype == CP_BODY_TYPE_DYNAMIC) { if (go->bodytype == CP_BODY_TYPE_DYNAMIC) {
nuke_property_float("Mass", 0.01f, &go->mass, 1000.f, 0.01f, 0.01f); nuke_property_float("Mass", 0.01f, &go->mass, 1000.f, 0.01f, 0.01f);
cpBodySetMass(go->body, go->mass); cpBodySetMass(go->body, go->mass);
} }
nuke_property_float("Friction", 0.f, &go->f, 10.f, 0.01f, 0.01f); nuke_property_float("Friction", 0.f, &go->f, 10.f, 0.01f, 0.01f);
nuke_property_float("Elasticity", 0.f, &go->e, 2.f, 0.01f, 0.01f); nuke_property_float("Elasticity", 0.f, &go->e, 2.f, 0.01f, 0.01f);
int n = -1; int n = -1;
for (int i = 0; i < arrlen(go->components); i++) { for (int i = 0; i < arrlen(go->components); i++) {
struct component *c = &go->components[i]; struct component *c = &go->components[i];
comp_draw_debug(c); comp_draw_debug(c);
nuke_nel(5); nuke_nel(5);
if (nuke_btn("Del")) n = i; if (nuke_btn("Del")) n = i;
if (nuke_push_tree_id(c->ref->name, i)) { if (nuke_push_tree_id(c->ref->name, i)) {
comp_draw_gui(c); comp_draw_gui(c);
nuke_tree_pop(); nuke_tree_pop();
} }
} }
if (n >= 0) if (n >= 0)
gameobject_delcomponent(go, n); gameobject_delcomponent(go, n);
*/ */
} }
void body_draw_shapes_dbg(cpBody *body, cpShape *shape, void *data) { void body_draw_shapes_dbg(cpBody *body, cpShape *shape, void *data) {
struct phys2d_shape *s = cpShapeGetUserData(shape); struct phys2d_shape *s = cpShapeGetUserData(shape);
s->debugdraw(s->data); s->debugdraw(s->data);
} }
void gameobject_draw_debug(int go) void gameobject_draw_debug(int go) {
{
struct gameobject *g = id2go(go); struct gameobject *g = id2go(go);
if (!g || !g->body) return; if (!g || !g->body) return;
@ -346,37 +327,40 @@ void gameobject_draw_debug(int go)
} }
void gameobject_draw_debugs() { void gameobject_draw_debugs() {
for (int i = 0; i < arrlen(gameobjects); i++) for (int i = 0; i < arrlen(gameobjects); i++)
gameobject_draw_debug(i); gameobject_draw_debug(i);
} }
static struct {
static struct {struct gameobject go; cpVect pos; float angle; } *saveobjects = NULL; struct gameobject go;
cpVect pos;
float angle;
} *saveobjects = NULL;
void gameobject_saveall() { void gameobject_saveall() {
arrfree(saveobjects); arrfree(saveobjects);
arrsetlen(saveobjects, arrlen(gameobjects)); arrsetlen(saveobjects, arrlen(gameobjects));
for (int i = 0; i < arrlen(gameobjects); i++) { for (int i = 0; i < arrlen(gameobjects); i++) {
saveobjects[i].go = gameobjects[i]; saveobjects[i].go = gameobjects[i];
saveobjects[i].pos = cpBodyGetPosition(gameobjects[i].body); saveobjects[i].pos = cpBodyGetPosition(gameobjects[i].body);
saveobjects[i].angle = cpBodyGetAngle(gameobjects[i].body); saveobjects[i].angle = cpBodyGetAngle(gameobjects[i].body);
} }
} }
void gameobject_loadall() { void gameobject_loadall() {
YughInfo("N gameobjects: %d, N saved: %d", arrlen(gameobjects), arrlen(saveobjects)); YughInfo("N gameobjects: %d, N saved: %d", arrlen(gameobjects), arrlen(saveobjects));
for (int i = 0; i < arrlen(saveobjects); i++) { for (int i = 0; i < arrlen(saveobjects); i++) {
gameobjects[i] = saveobjects[i].go; gameobjects[i] = saveobjects[i].go;
cpBodySetPosition(gameobjects[i].body, saveobjects[i].pos); cpBodySetPosition(gameobjects[i].body, saveobjects[i].pos);
cpBodySetAngle(gameobjects[i].body, saveobjects[i].angle); cpBodySetAngle(gameobjects[i].body, saveobjects[i].angle);
cpBodySetVelocity(gameobjects[i].body, cpvzero); cpBodySetVelocity(gameobjects[i].body, cpvzero);
cpBodySetAngularVelocity(gameobjects[i].body, 0.f); cpBodySetAngularVelocity(gameobjects[i].body, 0.f);
} }
arrfree(saveobjects); arrfree(saveobjects);
} }
int gameobjects_saved() { int gameobjects_saved() {
return arrlen(saveobjects); return arrlen(saveobjects);
} }

View file

@ -1,33 +1,33 @@
#ifndef GAMEOBJECT_H #ifndef GAMEOBJECT_H
#define GAMEOBJECT_H #define GAMEOBJECT_H
#include <stdio.h>
#include "mathc.h"
#include "config.h"
#include <stdbool.h>
#include <chipmunk/chipmunk.h>
#include "2dphysics.h" #include "2dphysics.h"
#include "config.h"
#include "mathc.h"
#include <chipmunk/chipmunk.h>
#include <stdbool.h>
#include <stdio.h>
struct shader; struct shader;
struct sprite; struct sprite;
struct component; struct component;
struct gameobject { struct gameobject {
cpBodyType bodytype; cpBodyType bodytype;
int next; int next;
float scale; float scale;
float mass; float mass;
float f; /* friction */ float f; /* friction */
float e; /* elasticity */ float e; /* elasticity */
int flipx; /* 1 or -1 */ int flipx; /* 1 or -1 */
int flipy; int flipy;
int sensor; int sensor;
unsigned int layer; unsigned int layer;
cpShapeFilter filter; cpShapeFilter filter;
cpBody *body; /* NULL if this object is dead */ cpBody *body; /* NULL if this object is dead */
int id; int id;
struct phys_cbs cbs; struct phys_cbs cbs;
struct shape_cb *shape_cbs; struct shape_cb *shape_cbs;
}; };
extern struct gameobject *gameobjects; extern struct gameobject *gameobjects;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,14 @@
#include "input.h" #include "input.h"
#include <stdio.h> #include "ffi.h"
#include "font.h"
#include "log.h"
#include "script.h" #include "script.h"
#include "stb_ds.h" #include "stb_ds.h"
#include "log.h"
#include "ffi.h"
#include "time.h" #include "time.h"
#include "font.h" #include <stdio.h>
#inlcude "stb_ds.h" #include "stb_ds.h"
int32_t mouseWheelX = 0; int32_t mouseWheelX = 0;
int32_t mouseWheelY = 0; int32_t mouseWheelY = 0;
@ -24,8 +24,8 @@ JSValue jsany;
JSValue jsmouse; JSValue jsmouse;
JSValue jspos; JSValue jspos;
cpVect mouse_pos = {0,0}; cpVect mouse_pos = {0, 0};
cpVect mouse_delta = {0,0}; cpVect mouse_delta = {0, 0};
struct joystick { struct joystick {
int id; int id;
@ -45,8 +45,7 @@ static struct {
JSValue value; JSValue value;
} *jshash = NULL; } *jshash = NULL;
JSValue input2js(const char *input) JSValue input2js(const char *input) {
{
int idx = shgeti(jshash, input); int idx = shgeti(jshash, input);
if (idx != -1) if (idx != -1)
return jshash[idx].value; return jshash[idx].value;
@ -60,36 +59,48 @@ JSValue input2js(const char *input)
return n; return n;
} }
const char *gamepad2str(int btn) const char *gamepad2str(int btn) {
{ switch (btn) {
switch(btn) { case GLFW_GAMEPAD_BUTTON_CROSS:
case GLFW_GAMEPAD_BUTTON_CROSS: return "cross"; return "cross";
case GLFW_GAMEPAD_BUTTON_CIRCLE: return "circle"; case GLFW_GAMEPAD_BUTTON_CIRCLE:
case GLFW_GAMEPAD_BUTTON_SQUARE: return "square"; return "circle";
case GLFW_GAMEPAD_BUTTON_TRIANGLE: return "triangle"; case GLFW_GAMEPAD_BUTTON_SQUARE:
case GLFW_GAMEPAD_BUTTON_START: return "start"; return "square";
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER: return "lbump"; case GLFW_GAMEPAD_BUTTON_TRIANGLE:
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER: return "rbump"; return "triangle";
case GLFW_GAMEPAD_BUTTON_GUIDE: return "guide"; case GLFW_GAMEPAD_BUTTON_START:
case GLFW_GAMEPAD_BUTTON_BACK: return "back"; return "start";
case GLFW_GAMEPAD_BUTTON_DPAD_UP: return "dup"; case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN: return "ddown"; return "lbump";
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT: return "dleft"; case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT: return "dright"; return "rbump";
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB: return "lthumb"; case GLFW_GAMEPAD_BUTTON_GUIDE:
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB: return "rthumb"; return "guide";
case GLFW_GAMEPAD_BUTTON_BACK:
return "back";
case GLFW_GAMEPAD_BUTTON_DPAD_UP:
return "dup";
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN:
return "ddown";
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT:
return "dleft";
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT:
return "dright";
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
return "lthumb";
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
return "rthumb";
} }
return "NOBTN"; return "NOBTN";
} }
void register_pawn(struct callee c) void register_pawn(struct callee c) {
{
pawn_callee = c; pawn_callee = c;
} }
void register_gamepad(struct callee c) void register_gamepad(struct callee c) {
{
gamepad_callee = c; gamepad_callee = c;
} }
@ -108,25 +119,23 @@ void rm_downkey(int key) {
} }
} }
static void cursor_pos_cb(GLFWwindow *w, double xpos, double ypos) static void cursor_pos_cb(GLFWwindow *w, double xpos, double ypos) {
{ mouse_delta.x = xpos - mouse_pos.x;
mouse_delta.x = xpos - mouse_pos.x; mouse_delta.y = ypos - mouse_pos.y;
mouse_delta.y = ypos - mouse_pos.y;
mouse_pos.x = xpos; mouse_pos.x = xpos;
mouse_pos.y = ypos; mouse_pos.y = ypos;
JSValue argv[4]; JSValue argv[4];
argv[0] = jsinput; argv[0] = jsinput;
argv[1] = jsmouse; argv[1] = jsmouse;
argv[2] = jspos; argv[2] = jspos;
argv[3] = vec2js(mouse_pos); argv[3] = vec2js(mouse_pos);
script_callee(pawn_callee, 4, argv); script_callee(pawn_callee, 4, argv);
JS_FreeValue(js, argv[3]); JS_FreeValue(js, argv[3]);
} }
static void pawn_call_keydown(int key) static void pawn_call_keydown(int key) {
{
JSValue argv[4]; JSValue argv[4];
argv[0] = jsinput; argv[0] = jsinput;
argv[1] = jsnum; argv[1] = jsnum;
@ -137,48 +146,44 @@ static void pawn_call_keydown(int key)
JS_FreeValue(js, argv[3]); JS_FreeValue(js, argv[3]);
} }
static void scroll_cb(GLFWwindow *w, double xoffset, double yoffset) static void scroll_cb(GLFWwindow *w, double xoffset, double yoffset) {
{ mouseWheelY = yoffset;
mouseWheelY = yoffset; mouseWheelX = xoffset;
mouseWheelX = xoffset;
} }
static void mb_cb(GLFWwindow *w, int button, int action, int mods) static void mb_cb(GLFWwindow *w, int button, int action, int mods) {
{
JSValue argv[3]; JSValue argv[3];
argv[0] = jsinput; argv[0] = jsinput;
switch (action) { switch (action) {
case GLFW_PRESS: case GLFW_PRESS:
argv[2] = jsinputstate[2]; argv[2] = jsinputstate[2];
add_downkey(button); add_downkey(button);
break; break;
case GLFW_RELEASE: case GLFW_RELEASE:
rm_downkey(button); rm_downkey(button);
argv[2] = jsinputstate[0]; argv[2] = jsinputstate[0];
argv[1] = jsany; argv[1] = jsany;
script_callee(pawn_callee,3,argv); script_callee(pawn_callee, 3, argv);
break; break;
case GLFW_REPEAT: case GLFW_REPEAT:
argv[2] = jsinputstate[1]; argv[2] = jsinputstate[1];
break; break;
} }
argv[1] = input2js(keyname_extd(button,button)); argv[1] = input2js(keyname_extd(button, button));
script_callee(pawn_callee,3,argv); script_callee(pawn_callee, 3, argv);
} }
void set_mouse_mode(int mousemode) void set_mouse_mode(int mousemode) {
{
glfwSetInputMode(mainwin->window, GLFW_CURSOR, mousemode); glfwSetInputMode(mainwin->window, GLFW_CURSOR, mousemode);
} }
void char_cb(GLFWwindow *w, unsigned int codepoint) void char_cb(GLFWwindow *w, unsigned int codepoint) {
{
static char out[2] = {0}; static char out[2] = {0};
static JSValue argv[2]; static JSValue argv[2];
out[0] = (char)codepoint; out[0] = (char)codepoint;
argv[0] = JS_NewString(js, "input_text"); argv[0] = JS_NewString(js, "input_text");
argv[1] = JS_NewString(js, out); argv[1] = JS_NewString(js, out);
@ -190,76 +195,70 @@ void char_cb(GLFWwindow *w, unsigned int codepoint)
static GLFWcharfun nukechar; static GLFWcharfun nukechar;
void joystick_add(int id) void joystick_add(int id) {
{
struct joystick joy = {0}; struct joystick joy = {0};
joy.id = id; joy.id = id;
arrpush(joysticks, joy); arrpush(joysticks, joy);
} }
void joystick_cb(int jid, int event) void joystick_cb(int jid, int event) {
{
YughWarn("IN joystick cb"); YughWarn("IN joystick cb");
if (event == GLFW_CONNECTED) { if (event == GLFW_CONNECTED) {
for (int i = 0; i < arrlen(joysticks); i++) for (int i = 0; i < arrlen(joysticks); i++)
if (joysticks[i].id == jid) return; if (joysticks[i].id == jid) return;
joystick_add(jid); joystick_add(jid);
} else if (event == GLFW_DISCONNECTED) { } else if (event == GLFW_DISCONNECTED) {
for (int i = 0; i < arrlen(joysticks); i++) { for (int i = 0; i < arrlen(joysticks); i++) {
if (joysticks[i].id == jid) { if (joysticks[i].id == jid) {
arrdelswap(joysticks,i); arrdelswap(joysticks, i);
return; return;
} }
} }
} }
} }
void input_init() {
glfwSetCursorPosCallback(mainwin->window, cursor_pos_cb);
glfwSetScrollCallback(mainwin->window, scroll_cb);
glfwSetMouseButtonCallback(mainwin->window, mb_cb);
glfwSetJoystickCallback(joystick_cb);
nukechar = glfwSetCharCallback(mainwin->window, char_cb);
void input_init() char *paddb = slurp_text("data/gamecontrollerdb.txt");
{ glfwUpdateGamepadMappings(paddb);
glfwSetCursorPosCallback(mainwin->window, cursor_pos_cb); free(paddb);
glfwSetScrollCallback(mainwin->window, scroll_cb);
glfwSetMouseButtonCallback(mainwin->window, mb_cb);
glfwSetJoystickCallback(joystick_cb);
nukechar = glfwSetCharCallback(mainwin->window, char_cb);
char *paddb = slurp_text("data/gamecontrollerdb.txt"); for (int b = 0; b < 15; b++)
glfwUpdateGamepadMappings(paddb); jsgamepadstr[b] = str2js(gamepad2str(b));
free(paddb);
for (int b = 0; b < 15; b++) jsaxesstr[0] = str2js("ljoy");
jsgamepadstr[b] = str2js(gamepad2str(b)); jsaxesstr[1] = str2js("rjoy");
jsaxesstr[2] = str2js("ltrigger");
jsaxesstr[3] = str2js("rtrigger");
jsaxis = str2js("axis");
jsaxesstr[0] = str2js("ljoy"); /* Grab all joysticks initially present */
jsaxesstr[1] = str2js("rjoy"); for (int i = 0; i < 16; i++)
jsaxesstr[2] = str2js("ltrigger"); if (glfwJoystickPresent(i)) joystick_add(i);
jsaxesstr[3] = str2js("rtrigger");
jsaxis = str2js("axis");
/* Grab all joysticks initially present */ jsinputstate[0] = str2js("released");
for (int i = 0; i < 16; i++) jsinputstate[1] = str2js("rep");
if (glfwJoystickPresent(i)) joystick_add(i); jsinputstate[2] = str2js("pressed");
jsinputstate[3] = str2js("pressrep");
jsinputstate[0] = str2js("released"); jsinputstate[4] = str2js("down");
jsinputstate[1] = str2js("rep"); jsinput = str2js("input");
jsinputstate[2] = str2js("pressed"); jsnum = str2js("num");
jsinputstate[3] = str2js("pressrep"); jsany = str2js("any");
jsinputstate[4] = str2js("down"); jsmouse = str2js("mouse");
jsinput = str2js("input"); jspos = str2js("pos");
jsnum = str2js("num");
jsany = str2js("any");
jsmouse = str2js("mouse");
jspos = str2js("pos");
} }
void input_to_nuke() void input_to_nuke() {
{
glfwSetCharCallback(mainwin->window, nukechar); glfwSetCharCallback(mainwin->window, nukechar);
} }
void input_to_game() void input_to_game() {
{
glfwSetCharCallback(mainwin->window, char_cb); glfwSetCharCallback(mainwin->window, char_cb);
} }
@ -272,308 +271,303 @@ void call_input_signal(char *signal) {
char keybuf[50]; char keybuf[50];
const char *keyname_extd(int key, int scancode) { const char *keyname_extd(int key, int scancode) {
const char *kkey = NULL; const char *kkey = NULL;
if (key > 289 && key < 302) { if (key > 289 && key < 302) {
int num = key-289; int num = key - 289;
sprintf(keybuf, "f%d", num); sprintf(keybuf, "f%d", num);
return keybuf; return keybuf;
} else if (key >= 320 && key <= 329) { } else if (key >= 320 && key <= 329) {
int num = key-320; int num = key - 320;
sprintf(keybuf, "kp%d",num); sprintf(keybuf, "kp%d", num);
return keybuf; return keybuf;
} else { } else {
switch(key) { switch (key) {
case GLFW_KEY_ENTER: case GLFW_KEY_ENTER:
kkey = "enter"; kkey = "enter";
break; break;
case GLFW_KEY_ESCAPE: case GLFW_KEY_ESCAPE:
kkey = "escape"; kkey = "escape";
break; break;
case GLFW_KEY_DELETE: case GLFW_KEY_DELETE:
kkey = "delete"; kkey = "delete";
break; break;
case GLFW_KEY_INSERT: case GLFW_KEY_INSERT:
kkey = "insert"; kkey = "insert";
break; break;
case GLFW_KEY_TAB: case GLFW_KEY_TAB:
kkey = "tab"; kkey = "tab";
break; break;
case GLFW_KEY_RIGHT: case GLFW_KEY_RIGHT:
kkey = "right"; kkey = "right";
break; break;
case GLFW_KEY_LEFT: case GLFW_KEY_LEFT:
kkey = "left"; kkey = "left";
break; break;
case GLFW_KEY_UP: case GLFW_KEY_UP:
kkey = "up"; kkey = "up";
break; break;
case GLFW_KEY_DOWN: case GLFW_KEY_DOWN:
kkey = "down"; kkey = "down";
break; break;
case GLFW_KEY_LEFT_SHIFT: case GLFW_KEY_LEFT_SHIFT:
kkey = "lshift"; kkey = "lshift";
break; break;
case GLFW_KEY_RIGHT_SHIFT: case GLFW_KEY_RIGHT_SHIFT:
kkey = "rshift"; kkey = "rshift";
break; break;
case GLFW_KEY_LEFT_CONTROL: case GLFW_KEY_LEFT_CONTROL:
kkey = "lctrl"; kkey = "lctrl";
break; break;
case GLFW_KEY_LEFT_ALT: case GLFW_KEY_LEFT_ALT:
kkey = "lalt"; kkey = "lalt";
break; break;
case GLFW_KEY_RIGHT_CONTROL: case GLFW_KEY_RIGHT_CONTROL:
kkey = "rctrl"; kkey = "rctrl";
break; break;
case GLFW_KEY_RIGHT_ALT: case GLFW_KEY_RIGHT_ALT:
kkey= "ralt"; kkey = "ralt";
break; break;
case GLFW_KEY_SPACE: case GLFW_KEY_SPACE:
kkey = "space"; kkey = "space";
break; break;
case GLFW_MOUSE_BUTTON_RIGHT:
kkey = "rmouse";
break;
case GLFW_MOUSE_BUTTON_LEFT: case GLFW_MOUSE_BUTTON_RIGHT:
kkey = "lmouse"; kkey = "rmouse";
break; break;
case GLFW_MOUSE_BUTTON_MIDDLE: case GLFW_MOUSE_BUTTON_LEFT:
kkey = "mmouse"; kkey = "lmouse";
break; break;
case GLFW_KEY_KP_ADD: case GLFW_MOUSE_BUTTON_MIDDLE:
kkey = "plus"; kkey = "mmouse";
break; break;
case GLFW_KEY_KP_SUBTRACT: case GLFW_KEY_KP_ADD:
kkey = "minus"; kkey = "plus";
break; break;
case GLFW_KEY_GRAVE_ACCENT:
kkey = "backtick";
break;
case GLFW_KEY_LEFT_BRACKET: case GLFW_KEY_KP_SUBTRACT:
kkey = "lbracket"; kkey = "minus";
break; break;
case GLFW_KEY_GRAVE_ACCENT:
kkey = "backtick";
break;
case GLFW_KEY_RIGHT_BRACKET: case GLFW_KEY_LEFT_BRACKET:
kkey = "rbracket"; kkey = "lbracket";
break; break;
case GLFW_KEY_BACKSPACE: case GLFW_KEY_RIGHT_BRACKET:
kkey = "backspace"; kkey = "rbracket";
break; break;
}
if (kkey) return kkey; case GLFW_KEY_BACKSPACE:
kkey = "backspace";
} break;
}
kkey = glfwGetKeyName(key, scancode);
if (kkey) return kkey; if (kkey) return kkey;
}
return "NULL"; kkey = glfwGetKeyName(key, scancode);
if (kkey) return kkey;
return "NULL";
} }
void call_input_down(int *key) { void call_input_down(int *key) {
JSValue argv[3]; JSValue argv[3];
argv[0] = jsinput; argv[0] = jsinput;
argv[1] = input2js(keyname_extd(*key, *key)); argv[1] = input2js(keyname_extd(*key, *key));
argv[2] = jsinputstate[4]; argv[2] = jsinputstate[4];
script_callee(pawn_callee,3,argv); script_callee(pawn_callee, 3, argv);
} }
const char *axis2str(int axis) {
const char *axis2str(int axis) switch (axis) {
{ case GLFW_GAMEPAD_AXIS_LEFT_X:
switch (axis) return "lx";
{ case GLFW_GAMEPAD_AXIS_LEFT_Y:
case GLFW_GAMEPAD_AXIS_LEFT_X: return "lx"; return "ly";
case GLFW_GAMEPAD_AXIS_LEFT_Y: return "ly"; case GLFW_GAMEPAD_AXIS_RIGHT_X:
case GLFW_GAMEPAD_AXIS_RIGHT_X: return "rx"; return "rx";
case GLFW_GAMEPAD_AXIS_RIGHT_Y: return "ry"; case GLFW_GAMEPAD_AXIS_RIGHT_Y:
case GLFW_GAMEPAD_AXIS_LEFT_TRIGGER: return "ltrigger"; return "ry";
case GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER: return "rtrigger"; case GLFW_GAMEPAD_AXIS_LEFT_TRIGGER:
return "ltrigger";
case GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER:
return "rtrigger";
} }
return "NOAXIS"; return "NOAXIS";
} }
/* This is called once every frame - or more if we want it more! */ /* This is called once every frame - or more if we want it more! */
void input_poll(double wait) void input_poll(double wait) {
{ mouse_delta = cpvzero;
mouse_delta = cpvzero; mouseWheelX = 0;
mouseWheelX = 0; mouseWheelY = 0;
mouseWheelY = 0;
glfwPollEvents(); glfwPollEvents();
// glfwWaitEventsTimeout(wait); // glfwWaitEventsTimeout(wait);
for (int i = 0; i < arrlen(downkeys); i++) for (int i = 0; i < arrlen(downkeys); i++)
call_input_down(&downkeys[i]); call_input_down(&downkeys[i]);
for (int i = 0; i < arrlen(joysticks); i++) { for (int i = 0; i < arrlen(joysticks); i++) {
GLFWgamepadstate state; GLFWgamepadstate state;
if (!glfwGetGamepadState(joysticks[i].id, &state)) continue; if (!glfwGetGamepadState(joysticks[i].id, &state)) continue;
JSValue argv[4]; JSValue argv[4];
argv[0] = num_cache[joysticks[i].id]; argv[0] = num_cache[joysticks[i].id];
for (int b = 0; b < 15; b++) { for (int b = 0; b < 15; b++) {
argv[1] = jsgamepadstr[b]; argv[1] = jsgamepadstr[b];
if (state.buttons[b]) { if (state.buttons[b]) {
argv[2] = num_cache[0]; argv[2] = num_cache[0];
script_callee(gamepad_callee,3,argv); script_callee(gamepad_callee, 3, argv);
if (!joysticks[i].state.buttons[b]) { if (!joysticks[i].state.buttons[b]) {
argv[2] = num_cache[1]; argv[2] = num_cache[1];
script_callee(gamepad_callee,3,argv); script_callee(gamepad_callee, 3, argv);
} }
} } else if (!state.buttons[b] && joysticks[i].state.buttons[b]) {
else if (!state.buttons[b] && joysticks[i].state.buttons[b]) { argv[2] = num_cache[2];
argv[2] = num_cache[2]; script_callee(gamepad_callee, 3, argv);
script_callee(gamepad_callee,3,argv);
}
} }
argv[2] = jsaxis;
float deadzone = 0.05;
for (int i = 0; i < 4; i++)
state.axes[i] = fabs(state.axes[i]) > deadzone ? state.axes[i] : 0;
argv[1] = jsaxesstr[0];
cpVect v;
v.x = state.axes[0];
v.y = -state.axes[1];
argv[3] = vec2js(v);
script_callee(gamepad_callee,4,argv);
JS_FreeValue(js, argv[3]);
argv[1] = jsaxesstr[1];
v.x = state.axes[2];
v.y = -state.axes[3];
argv[3] = vec2js(v);
script_callee(gamepad_callee,4,argv);
JS_FreeValue(js, argv[3]);
argv[1] = jsaxesstr[2];
argv[3] = num2js((state.axes[4]+1)/2);
script_callee(gamepad_callee,4,argv);
JS_FreeValue(js, argv[3]);
argv[1] = jsaxesstr[3];
argv[3] = num2js((state.axes[5]+1)/2);
script_callee(gamepad_callee,4,argv);
JS_FreeValue(js, argv[3]);
joysticks[i].state = state;
} }
argv[2] = jsaxis;
float deadzone = 0.05;
for (int i = 0; i < 4; i++)
state.axes[i] = fabs(state.axes[i]) > deadzone ? state.axes[i] : 0;
argv[1] = jsaxesstr[0];
cpVect v;
v.x = state.axes[0];
v.y = -state.axes[1];
argv[3] = vec2js(v);
script_callee(gamepad_callee, 4, argv);
JS_FreeValue(js, argv[3]);
argv[1] = jsaxesstr[1];
v.x = state.axes[2];
v.y = -state.axes[3];
argv[3] = vec2js(v);
script_callee(gamepad_callee, 4, argv);
JS_FreeValue(js, argv[3]);
argv[1] = jsaxesstr[2];
argv[3] = num2js((state.axes[4] + 1) / 2);
script_callee(gamepad_callee, 4, argv);
JS_FreeValue(js, argv[3]);
argv[1] = jsaxesstr[3];
argv[3] = num2js((state.axes[5] + 1) / 2);
script_callee(gamepad_callee, 4, argv);
JS_FreeValue(js, argv[3]);
joysticks[i].state = state;
}
} }
int key_is_num(int key) { int key_is_num(int key) {
return key <= 57 && key >= 48; return key <= 57 && key >= 48;
} }
void win_key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) void win_key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) {
{ JSValue argv[3];
JSValue argv[3]; argv[0] = jsinput;
argv[0] = jsinput; argv[1] = input2js(keyname_extd(key, scancode));
argv[1] = input2js(keyname_extd(key,scancode));
switch (action) { switch (action) {
case GLFW_PRESS: case GLFW_PRESS:
argv[2] = jsinputstate[2]; argv[2] = jsinputstate[2];
script_callee(pawn_callee, 3, argv); script_callee(pawn_callee, 3, argv);
argv[2] = jsinputstate[3]; argv[2] = jsinputstate[3];
script_callee(pawn_callee,3,argv); script_callee(pawn_callee, 3, argv);
add_downkey(key); add_downkey(key);
argv[1] = jsany; argv[1] = jsany;
argv[2] = jsinputstate[2]; argv[2] = jsinputstate[2];
script_callee(pawn_callee,3,argv); script_callee(pawn_callee, 3, argv);
if (key_is_num(key))
pawn_call_keydown(key-48);
break;
case GLFW_RELEASE: if (key_is_num(key))
argv[2] = jsinputstate[0]; pawn_call_keydown(key - 48);
script_callee(pawn_callee,3,argv);
rm_downkey(key);
argv[1] = jsany;
script_callee(pawn_callee,3,argv);
break;
case GLFW_REPEAT: break;
argv[2] = jsinputstate[1];
script_callee(pawn_callee,3,argv); case GLFW_RELEASE:
argv[2] = jsinputstate[3]; argv[2] = jsinputstate[0];
script_callee(pawn_callee,3,argv); script_callee(pawn_callee, 3, argv);
break; rm_downkey(key);
argv[1] = jsany;
script_callee(pawn_callee, 3, argv);
break;
case GLFW_REPEAT:
argv[2] = jsinputstate[1];
script_callee(pawn_callee, 3, argv);
argv[2] = jsinputstate[3];
script_callee(pawn_callee, 3, argv);
break;
}
}
void cursor_hide() {
glfwSetInputMode(mainwin->window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
void cursor_show() {
glfwSetInputMode(mainwin->window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
int action_down(int scancode) {
for (int i = 0; i < arrlen(downkeys); i++) {
if (downkeys[i] == scancode)
return 1;
}
return 0;
}
int action_up(int scancode) {
int found = 0;
for (int i = 0; i < arrlen(downkeys); i++) {
if (downkeys[i] == scancode) {
found = 1;
break;
} }
} }
void cursor_hide() return !found;
{
glfwSetInputMode(mainwin->window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
void cursor_show()
{
glfwSetInputMode(mainwin->window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
int action_down(int scancode)
{
for (int i = 0; i < arrlen(downkeys); i++) {
if (downkeys[i] == scancode)
return 1;
}
return 0;
}
int action_up(int scancode)
{
int found = 0;
for (int i = 0; i < arrlen(downkeys); i++) {
if (downkeys[i] == scancode) {
found = 1;
break;
}
}
return !found;
} }
int want_quit() { int want_quit() {
return mquit; return mquit;
} }
void quit() { void quit() {
YughInfo("Exiting game."); YughInfo("Exiting game.");
mquit = 1; mquit = 1;
} }

View file

@ -1,10 +1,10 @@
#ifndef INPUT_H #ifndef INPUT_H
#define INPUT_H #define INPUT_H
#include <stdint.h> #include "script.h"
#include "window.h" #include "window.h"
#include <chipmunk/chipmunk.h> #include <chipmunk/chipmunk.h>
#include "script.h" #include <stdint.h>
extern int32_t mouseWheelX; extern int32_t mouseWheelX;
extern int32_t mouseWheelY; extern int32_t mouseWheelY;
@ -33,9 +33,8 @@ void quit();
void win_key_callback(GLFWwindow *w, int key, int scancode, int action, int mods); void win_key_callback(GLFWwindow *w, int key, int scancode, int action, int mods);
struct inputaction struct inputaction {
{ int scancode;
int scancode;
}; };
void input_to_nuke(); void input_to_nuke();

View file

@ -1,53 +1,49 @@
#include "level.h" #include "level.h"
#include <stdio.h>
#include <string.h>
#include "gameobject.h" #include "gameobject.h"
#include "resources.h" #include "resources.h"
#include <stdio.h>
#include <string.h>
#include "stb_ds.h" #include "stb_ds.h"
void save_level(char name[MAXNAME]) void save_level(char name[MAXNAME]) {
{ FILE *lfile = res_open(name, "wb+");
FILE *lfile = res_open(name, "wb+");
if (!lfile) return; if (!lfile) return;
int objs = arrlen(gameobjects);
fwrite(&objs, sizeof(objs), 1, lfile);
int objs = arrlen(gameobjects); fclose(lfile);
fwrite(&objs, sizeof(objs), 1, lfile);
fclose(lfile);
} }
void load_level(char name[MAXNAME]) void load_level(char name[MAXNAME]) {
{ /*
/* FILE *lfile = fopen(name, "rb");
FILE *lfile = fopen(name, "rb");
if (!lfile) return; if (!lfile) return;
new_level(); new_level();
int objs; int objs;
fread(&objs, sizeof(objs), 1, lfile); fread(&objs, sizeof(objs), 1, lfile);
arraddn(gameobjects, objs); arraddn(gameobjects, objs);
for (int i = 0; i < objs; i++) { for (int i = 0; i < objs; i++) {
struct gameobject *go = &gameobjects[i]; struct gameobject *go = &gameobjects[i];
fread(go, sizeof(struct gameobject), 1, lfile); fread(go, sizeof(struct gameobject), 1, lfile);
go->components = NULL; go->components = NULL;
gameobject_init(go, lfile); gameobject_init(go, lfile);
} }
fclose(lfile); fclose(lfile);
*/ */
} }
void new_level() void new_level() {
{ for (int i = 0; i < arrlen(gameobjects); i++)
for (int i = 0; i < arrlen(gameobjects); i++) gameobject_delete(i);
gameobject_delete(i);
arrfree(gameobjects); arrfree(gameobjects);
} }

View file

@ -6,12 +6,11 @@
// This class holds all of the entities and options for a level. Really it's nothing more than a container and access point for all the entities currently loaded into the game. // This class holds all of the entities and options for a level. Really it's nothing more than a container and access point for all the entities currently loaded into the game.
struct level { struct level {
char name[MAXNAME]; char name[MAXNAME];
}; };
void save_level(char name[MAXNAME]); void save_level(char name[MAXNAME]);
void load_level(char name[MAXNAME]); void load_level(char name[MAXNAME]);
void new_level(); void new_level();
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,155 +1,147 @@
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO #define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_STANDARD_BOOL
#define NK_IMPLEMENTATION #define NK_IMPLEMENTATION
#define NK_GLFW_GL3_IMPLEMENTATION
#define NK_KEYSTATE_BASED_INPUT #define NK_KEYSTATE_BASED_INPUT
#define STBTT_STATIC
#include "nuke.h" #include "nuke.h"
#include "nuklear_glfw_gl3.h"
#define SOKOL_GLCORE33
#include "sokol/sokol_gfx.h"
#define SOKOL_NUKLEAR_NO_SOKOL_APP
#define SOKOL_NUKLEAR_IMPL
#include "sokol/sokol_nuklear.h"
#include <stdarg.h> #include <stdarg.h>
#include "window.h"
#include "texture.h"
#include "log.h" #include "log.h"
#include "texture.h"
#include "window.h"
#define MAX_VERTEX_BUFFER 512 * 1024 #define MAX_VERTEX_BUFFER 512 * 1024
#define MAX_ELEMENT_BUFFER 128 * 1024 #define MAX_ELEMENT_BUFFER 128 * 1024
struct nk_context *ctx; struct nk_context *ctx;
static struct nk_glfw nkglfw = {0}; //static struct nk_glfw nkglfw = {0};
void nuke_init(struct window *win) { void nuke_init(struct window *win) {
window_makecurrent(win); window_makecurrent(win);
ctx = nk_glfw3_init(&nkglfw, win->window, NK_GLFW3_INSTALL_CALLBACKS); snk_setup(&(snk_desc_t){
.no_default_font = false
struct nk_font_atlas *atlas; });
nk_glfw3_font_stash_begin(&nkglfw, &atlas);
struct nk_font *noto = nk_font_atlas_add_from_file(atlas, "fonts/teenytinypixels.tff", 14, 0);
nk_glfw3_font_stash_end(&nkglfw);
} }
void nuke_start() void nuke_start() {
{ ctx = snk_new_frame();
nk_glfw3_new_frame(&nkglfw);
} }
void nuke_end() void nuke_end() {
{ snk_render(1200,720);
nk_glfw3_render(&nkglfw, NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER);
} }
int nuke_begin(const char *lbl, struct nk_rect rect, int flags) { int nuke_begin(const char *lbl, struct nk_rect rect, int flags) {
return nk_begin(ctx, lbl, rect, flags); return nk_begin(ctx, lbl, rect, flags);
} }
int nuke_begin_win(const char *lbl) int nuke_begin_win(const char *lbl) {
{
return nk_begin(ctx, lbl, nk_rect(10, 10, 400, 600), NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE | NK_WINDOW_TITLE); return nk_begin(ctx, lbl, nk_rect(10, 10, 400, 600), NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE | NK_WINDOW_TITLE);
} }
void nuke_stop() { void nuke_stop() {
nk_end(ctx); nk_end(ctx);
} }
struct nk_rect nuke_win_get_bounds() { struct nk_rect nuke_win_get_bounds() {
return nk_window_get_bounds(ctx); return nk_window_get_bounds(ctx);
} }
void nuke_row(int height) void nuke_row(int height) {
{
nk_layout_row_dynamic(ctx, height, 1); nk_layout_row_dynamic(ctx, height, 1);
} }
void nuke_property_float3(const char *label, float min, float *val, float max, float step, float dragstep) { void nuke_property_float3(const char *label, float min, float *val, float max, float step, float dragstep) {
nk_layout_row_dynamic(ctx, 25, 1); nk_layout_row_dynamic(ctx, 25, 1);
nk_label(ctx, label, NK_TEXT_LEFT); nk_label(ctx, label, NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 25, 3); nk_layout_row_dynamic(ctx, 25, 3);
nuke_property_float("#X", min, &val[0], max, step, dragstep); nuke_property_float("#X", min, &val[0], max, step, dragstep);
nuke_property_float("#Y", min, &val[1], max, step, dragstep); nuke_property_float("#Y", min, &val[1], max, step, dragstep);
nuke_property_float("#Z", min, &val[2], max, step, dragstep); nuke_property_float("#Z", min, &val[2], max, step, dragstep);
} }
void nuke_property_float2(const char *label, float min, float *val, float max, float step, float dragstep) { void nuke_property_float2(const char *label, float min, float *val, float max, float step, float dragstep) {
nk_layout_row_dynamic(ctx, 25, 1); nk_layout_row_dynamic(ctx, 25, 1);
nk_label(ctx, label, NK_TEXT_LEFT); nk_label(ctx, label, NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 25, 2); nk_layout_row_dynamic(ctx, 25, 2);
nuke_property_float("#X", min, &val[0], max, step, dragstep); nuke_property_float("#X", min, &val[0], max, step, dragstep);
nuke_property_float("#Y", min, &val[1], max, step, dragstep); nuke_property_float("#Y", min, &val[1], max, step, dragstep);
} }
void nuke_property_float(const char *lbl, float min, float *val, float max, float step, float dragstep) { void nuke_property_float(const char *lbl, float min, float *val, float max, float step, float dragstep) {
nk_property_float(ctx, lbl, min, val, max, step, dragstep); nk_property_float(ctx, lbl, min, val, max, step, dragstep);
} }
int nuke_btn(const char *lbl) { int nuke_btn(const char *lbl) {
return nk_button_label(ctx, lbl); return nk_button_label(ctx, lbl);
} }
void nuke_img(char *path) { void nuke_img(char *path) {
/* /*
struct Texture *t = texture_pullfromfile(path); struct Texture *t = texture_pullfromfile(path);
nk_layout_row_static(ctx, t->height, t->width, 1); nk_layout_row_static(ctx, t->height, t->width, 1);
nk_image(ctx, nk_image_id(t->id)); nk_image(ctx, nk_image_id(t->id));
*/ */
} }
void nuke_property_int(const char *lbl, int min, int *val, int max, int step) { void nuke_property_int(const char *lbl, int min, int *val, int max, int step) {
nk_property_int(ctx, lbl, min, val, max, step, step); nk_property_int(ctx, lbl, min, val, max, step, step);
} }
void nuke_radio_btn(const char *lbl, int *val, int cmp) { void nuke_radio_btn(const char *lbl, int *val, int cmp) {
if (nk_option_label(ctx, lbl, *val==cmp)) *val = cmp; if (nk_option_label(ctx, lbl, *val == cmp)) *val = cmp;
} }
void nuke_checkbox(const char *lbl, int *val) { void nuke_checkbox(const char *lbl, int *val) {
nk_checkbox_label(ctx, lbl, val); nk_checkbox_label(ctx, lbl, val);
} }
void nuke_scrolltext(char *str) void nuke_scrolltext(char *str) {
{ nk_edit_string_zero_terminated(ctx, NK_EDIT_MULTILINE | NK_EDIT_GOTO_END_ON_ACTIVATE, str, 1024 * 1024 * 5, NULL);
nk_edit_string_zero_terminated(ctx, NK_EDIT_MULTILINE|NK_EDIT_GOTO_END_ON_ACTIVATE, str, 1024*1024*5, NULL);
} }
void nuke_nel(int cols) { void nuke_nel(int cols) {
nk_layout_row_dynamic(ctx, 25, cols); nk_layout_row_dynamic(ctx, 25, cols);
} }
void nuke_nel_h(int cols, int h) { void nuke_nel_h(int cols, int h) {
nk_layout_row_dynamic(ctx, h, cols); nk_layout_row_dynamic(ctx, h, cols);
} }
void nuke_label(const char *s) { void nuke_label(const char *s) {
nk_label(ctx, s, NK_TEXT_LEFT); nk_label(ctx, s, NK_TEXT_LEFT);
} }
void nuke_edit_str(char *str) { void nuke_edit_str(char *str) {
nk_edit_string_zero_terminated(ctx, NK_EDIT_BOX|NK_EDIT_NO_HORIZONTAL_SCROLL, str, 130, nk_filter_ascii); nk_edit_string_zero_terminated(ctx, NK_EDIT_BOX | NK_EDIT_NO_HORIZONTAL_SCROLL, str, 130, nk_filter_ascii);
} }
int nuke_push_tree_id(const char *name, int id) { int nuke_push_tree_id(const char *name, int id) {
return nk_tree_push_id(ctx, NK_TREE_NODE, name, NK_MINIMIZED, id); return nk_tree_push_id(ctx, NK_TREE_NODE, name, NK_MINIMIZED, id);
} }
void nuke_tree_pop() { void nuke_tree_pop() {
nk_tree_pop(ctx); nk_tree_pop(ctx);
} }
void nuke_labelf(const char *fmt, ...) { void nuke_labelf(const char *fmt, ...) {
char buf[512]; char buf[512];
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
vsnprintf(buf, 512, fmt, args); vsnprintf(buf, 512, fmt, args);
nuke_label(buf); nuke_label(buf);
va_end(args); va_end(args);
} }

View file

@ -1,6 +1,14 @@
#ifndef NUKE_H #ifndef NUKE_H
#define NUKE_H #define NUKE_H
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_STANDARD_BOOL
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#include "nuklear.h" #include "nuklear.h"
struct window; struct window;

View file

@ -1,16 +1,20 @@
#include "openglrender.h" #include "openglrender.h"
#include "sprite.h"
#include "shader.h"
#include "font.h"
#include "config.h"
#include "gameobject.h"
#include "camera.h" #include "camera.h"
#include "window.h" #include "config.h"
#include "debugdraw.h"
#include "log.h"
#include "datastream.h" #include "datastream.h"
#include "debugdraw.h"
#include "font.h"
#include "gameobject.h"
#include "log.h"
#include "nuke.h" #include "nuke.h"
#include "shader.h"
#include "sprite.h"
#include "window.h"
#include "model.h"
#include "stb_ds.h"
#include "HandmadeMath.h"
int renderMode = LIT; int renderMode = LIT;
@ -19,13 +23,13 @@ struct shader *wireframeShader = NULL;
struct shader *animSpriteShader = NULL; struct shader *animSpriteShader = NULL;
static struct shader *textShader; static struct shader *textShader;
mfloat_t editorClearColor[4] = { 0.2f, 0.4f, 0.3f, 1.f }; mfloat_t editorClearColor[4] = {0.2f, 0.4f, 0.3f, 1.f};
float shadowLookahead = 8.5f; float shadowLookahead = 8.5f;
mfloat_t gridSmallColor[3] = { 0.35f, 1.f, 0.9f }; mfloat_t gridSmallColor[3] = {0.35f, 1.f, 0.9f};
mfloat_t gridBigColor[3] = { 0.92f, 0.92f, 0.68f }; mfloat_t gridBigColor[3] = {0.92f, 0.92f, 0.68f};
float gridScale = 500.f; float gridScale = 500.f;
float smallGridUnit = 1.f; float smallGridUnit = 1.f;
@ -50,130 +54,263 @@ bool renderReflection = true;
///// for editing ///// for editing
struct gameobject *selectedobject = NULL; struct gameobject *selectedobject = NULL;
char objectName[200] = { '\0' }; // object name buffer char objectName[200] = {'\0'}; // object name buffer
struct sprite *tsprite = NULL; struct sprite *tsprite = NULL;
const char *donquixote; const char *donquixote;
static struct model *duck;
sg_image ddimg;
void debug_draw_phys(int draw) { void debug_draw_phys(int draw) {
debugDrawPhysics = draw; debugDrawPhysics = draw;
} }
void opengl_rendermode(enum RenderMode r) void opengl_rendermode(enum RenderMode r) {
{
renderMode = r; renderMode = r;
} }
sg_pipeline mainpip; sg_pipeline mainpip;
sg_pass_action pass_action = {0}; sg_pass_action pass_action = {0};
void openglInit() static struct {
{ sg_pass_action pass_action;
if (!mainwin) { sg_pass pass;
YughError("No window to init OpenGL on.", 1); sg_pipeline pipe;
exit(1); sg_shader shader;
} sg_shadow;
static struct {
sg_shader shader;
sg_pipeline pipe;
sg_bindings bind;
sg_pass pass;
sg_image img;
sg_image depth_img;
} crt_post;
void openglInit() {
if (!mainwin) {
YughError("No window to init OpenGL on.", 1);
exit(1);
}
font_init(NULL);
debugdraw_init();
sprite_initialize();
nuke_init(mainwin);
model_init();
// duck = MakeModel("sponza.glb");
pass_action = (sg_pass_action){
.colors[0] = {.action = SG_ACTION_CLEAR, .value = {editorClearColor[1], editorClearColor[2], editorClearColor[3], 1.f}},
};
crt_post.shader = sg_make_shader(&(sg_shader_desc){
.vs.source = slurp_text("shaders/postvert.glsl"),
.fs.source = slurp_text("shaders/crtfrag.glsl"),
.fs.images[0] = {
.name = "diffuse_texture",
.image_type = SG_IMAGETYPE_2D,
.sampler_type = SG_SAMPLERTYPE_FLOAT
} }
});
// donquixote = slurp_text("quixote.txt"); crt_post.pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = crt_post.shader,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT2,
[1].format = SG_VERTEXFORMAT_FLOAT2
}
}
});
////// MAKE SHADERS crt_post.img = sg_make_image(&(sg_image_desc){
spriteShader = MakeShader("spritevert.glsl", "spritefrag.glsl"); .render_target = true,
wireframeShader = MakeShader("spritevert.glsl", "spritewireframefrag.glsl"); .width = 1200,
animSpriteShader = MakeShader("animspritevert.glsl", "animspritefrag.glsl"); .height = 720,
textShader = MakeShader("textvert.glsl", "textfrag.glsl"); });
font_init(textShader); crt_post.depth_img = sg_make_image(&(sg_image_desc){
sprite_initialize(); .render_target = true,
debugdraw_init(); .width = 1200,
.height = 720,
.pixel_format = SG_PIXELFORMAT_DEPTH_STENCIL
});
glClearColor(editorClearColor[0], editorClearColor[1], editorClearColor[2], editorClearColor[3]); crt_post.pass = sg_make_pass(&(sg_pass_desc){
.color_attachments[0].image = crt_post.img,
.depth_stencil_attachment.image = crt_post.depth_img,
});
float crt_quad[] = {
-1, 1, 0, 1,
-1, -1, 0, 0,
1, -1, 1, 0,
-1, 1, 0, 1,
1, -1, 1, 0,
1, 1, 1, 1
};
crt_post.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(crt_quad),
.data = crt_quad
});
crt_post.bind.fs_images[0] = crt_post.img;
/* /*
glCullFace(GL_BACK); sg_image_desc shadow_desc = {
.render_target = true,
.width = 1024,
.height = 1024,
.pixel_format = SG_PIXELFORMAT_R32F,
};
sg_image depth_img = sg_make_image(&shadow_desc);
shadow_desc.pixel_format = SG_PIXELFORMAT_DEPTH;
ddimg = sg_make_image(&shadow_desc);
glEnable(GL_BLEND); duck = MakeModel("sponza.glb");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
sg_shadow.pass = sg_make_pass(&(sg_pass_desc){
.color_attachments[0].image = depth_img,
.depth_stencil_attachment.image = ddimg,
});
sg_shadow.pass_action = (sg_pass_action) {
.colors[0] = { .action=SG_ACTION_CLEAR, .value = {1,1,1,1} } };
glGenBuffers(1, &projUBO); sg_shadow.shader = sg_make_shader(&(sg_shader_desc){
glBindBuffer(GL_UNIFORM_BUFFER, projUBO); .vs.source = slurp_text("shaders/shadowvert.glsl"),
glBufferData(GL_UNIFORM_BUFFER, 64, NULL, GL_DYNAMIC_DRAW); .fs.source = slurp_text("shaders/shadowfrag.glsl"),
glBindBufferRange(GL_UNIFORM_BUFFER, 0, projUBO, 0, sizeof(float) * 16); .vs.uniform_blocks[0] = {
glBindBuffer(GL_UNIFORM_BUFFER, 0); .size = sizeof(float) * 16 * 2,
.uniforms = {
[0] = {.name = "lightSpaceMatrix", .type = SG_UNIFORMTYPE_MAT4},
[1] = {.name = "model", .type = SG_UNIFORMTYPE_MAT4},
}
}
});
shader_setUBO(spriteShader, "Projection", 0); sg_shadow.pipe = sg_make_pipeline(&(sg_pipeline_desc){
shader_setUBO(textShader, "Projection", 0); .shader = sg_shadow.shader,
shader_setUBO(animSpriteShader, "Projection", 0); .layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT3,
}
},
.depth = {
.compare = SG_COMPAREFUNC_LESS_EQUAL,
.write_enabled = true,
.pixel_format = SG_PIXELFORMAT_DEPTH
},
.colors[0].pixel_format = SG_PIXELFORMAT_R32F,
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_BACK,
});
*/ */
} }
static cpBody *camera = NULL; static cpBody *camera = NULL;
void set_cam_body(cpBody *body) { void set_cam_body(cpBody *body) {
camera = body; camera = body;
} }
cpVect cam_pos() { cpVect cam_pos() {
return camera ? cpBodyGetPosition(camera) : cpvzero; return camera ? cpBodyGetPosition(camera) : cpvzero;
} }
static float zoom = 1.f; static float zoom = 1.f;
float cam_zoom() { return zoom; } float cam_zoom() { return zoom; }
void add_zoom(float val) { zoom = val; } void add_zoom(float val) { zoom = val; }
mfloat_t projection[16] = {0.f}; mfloat_t projection[16] = {0.f};
void openglRender(struct window *window) HMM_Vec3 dirl_pos = {4, 100, 20};
{
sg_begin_default_pass(&pass_action, window->width, window->height);
//////////// 2D projection void openglRender(struct window *window) {
cpVect pos = cam_pos(); /*
HMM_Mat4 model = HMM_M4D(1.f);
float scale = 0.08;
model = HMM_MulM4(model, HMM_Scale((HMM_Vec3){scale,scale,scale}));
mat4_ortho(projection, pos.x - zoom*window->width/2,
pos.x + zoom*window->width/2,
pos.y - zoom*window->height/2,
pos.y + zoom*window->height/2, -1.f, 1.f);
mfloat_t ui_projection[16] = { 0.f }; // Shadow pass
mat4_ortho(ui_projection, 0, sg_begin_pass(sg_shadow.pass, &sg_shadow.pass_action);
window->width, sg_apply_pipeline(sg_shadow.pipe);
0,
window->height, -1.f, 1.f);
sprite_draw_all(); HMM_Mat4 light_proj = HMM_Orthographic_RH_ZO(-100.f, 100.f, -100.f, 100.f, 1.f, 100.f);
gui_draw_img("pill1.png", 200, 200); HMM_Mat4 light_view = HMM_LookAt_RH(dirl_pos, (HMM_Vec3){0,0,0}, (HMM_Vec3){0,1,0});
float a[2] = {100,100};
float w[3] = {1.f,1.f,1.f};
renderText("TEST RENDER", a, 1.f, w, 0,-1);
float b[2] = {50,50};
renderText("TEST @@@@ RENDER", b, 1.f, w, 0,-1);
/* UI Elements & Debug elements */ HMM_Mat4 lsm = HMM_MulM4(light_proj, light_view);
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// glDisable(GL_DEPTH_TEST);
//// DEBUG
// if (debugDrawPhysics)
// gameobject_draw_debugs();
// call_debugs(); HMM_Mat4 subo[2];
subo[0] = lsm;
subo[1] = model;
////// TEXT && GUI sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(subo));
// glBindBuffer(GL_UNIFORM_BUFFER, projUBO);
// glBufferSubData(GL_UNIFORM_BUFFER, 0, 64, ui_projection); for (int i = 0; i < arrlen(duck->meshes); i++) {
text_flush(); sg_bindings sbind = {0};
sbind.vertex_buffers[0] = duck->meshes[i].bind.vertex_buffers[0];
sbind.index_buffer = duck->meshes[i].bind.index_buffer;
sg_apply_bindings(&sbind);
sg_draw(0,duck->meshes[i].face_count,1);
}
sg_end_pass();
// call_gui(); draw_model(duck,model, lsm);
*/
// nuke_start(); // sg_begin_default_pass(&pass_action, window->width, window->height);
// call_nk_gui(); sg_begin_pass(crt_post.pass, &pass_action);
// nuke_end();
//////////// 2D projection
cpVect pos = cam_pos();
mat4_ortho(projection, pos.x - zoom * window->width / 2,
pos.x + zoom * window->width / 2,
pos.y - zoom * window->height / 2,
pos.y + zoom * window->height / 2, -1.f, 1.f);
mfloat_t ui_projection[16] = {0.f};
mat4_ortho(ui_projection, 0, window->width, 0, window->height, -1.f, 1.f);
sprite_draw_all();
sprite_flush();
//// DEBUG
if (debugDrawPhysics)
gameobject_draw_debugs();
call_debugs();
debug_flush();
////// TEXT && GUI
call_gui();
text_flush();
nuke_start();
call_nk_gui();
nuke_end();
sg_end_pass(); sg_end_pass();
sg_commit();
sg_begin_default_pass(&pass_action, window->width, window->height);
sg_apply_pipeline(crt_post.pipe);
sg_apply_bindings(&crt_post.bind);
sg_draw(0,6,1);
sg_end_pass();
sprite_flush(); sg_commit();
} }

View file

@ -1,16 +1,23 @@
#ifndef OPENGL_RENDER_H #ifndef OPENGL_RENDER_H
#define OPENGL_RENDER_H #define OPENGL_RENDER_H
#include "sokol/sokol_gfx.h"
#include "HandmadeMath.h"
struct mCamera; struct mCamera;
struct window; struct window;
extern struct shader *spriteShader; extern struct shader *spriteShader;
extern struct shader *animSpriteShader; extern struct shader *animSpriteShader;
extern sg_image ddimg;
extern struct sprite *tsprite; extern struct sprite *tsprite;
extern int renderMode; extern int renderMode;
extern HMM_Vec3 dirl_pos;
extern float projection[16]; extern float projection[16];
extern float gridScale; extern float gridScale;

File diff suppressed because it is too large Load diff

View file

@ -27,8 +27,7 @@
#define parson_parson_h #define parson_parson_h
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
#if 0 #if 0
} /* unconfuse xcode */ } /* unconfuse xcode */
@ -40,32 +39,32 @@ extern "C"
#define PARSON_VERSION_STRING "1.4.0" #define PARSON_VERSION_STRING "1.4.0"
#include <stddef.h> /* size_t */ #include <stddef.h> /* size_t */
/* Types and enums */ /* Types and enums */
typedef struct json_object_t JSON_Object; typedef struct json_object_t JSON_Object;
typedef struct json_array_t JSON_Array; typedef struct json_array_t JSON_Array;
typedef struct json_value_t JSON_Value; typedef struct json_value_t JSON_Value;
enum json_value_type { enum json_value_type {
JSONError = -1, JSONError = -1,
JSONNull = 1, JSONNull = 1,
JSONString = 2, JSONString = 2,
JSONNumber = 3, JSONNumber = 3,
JSONObject = 4, JSONObject = 4,
JSONArray = 5, JSONArray = 5,
JSONBoolean = 6 JSONBoolean = 6
}; };
typedef int JSON_Value_Type; typedef int JSON_Value_Type;
enum json_result_t { enum json_result_t {
JSONSuccess = 0, JSONSuccess = 0,
JSONFailure = -1 JSONFailure = -1
}; };
typedef int JSON_Status; typedef int JSON_Status;
typedef void * (*JSON_Malloc_Function)(size_t); typedef void *(*JSON_Malloc_Function)(size_t);
typedef void (*JSON_Free_Function)(void *); typedef void (*JSON_Free_Function)(void *);
/* Call only once, before calling any other function from parson API. If not called, malloc and free /* Call only once, before calling any other function from parson API. If not called, malloc and free
from stdlib will be used for all allocations */ from stdlib will be used for all allocations */
@ -81,35 +80,35 @@ void json_set_escape_slashes(int escape_slashes);
void json_set_float_serialization_format(const char *format); void json_set_float_serialization_format(const char *format);
/* Parses first JSON value in a file, returns NULL in case of error */ /* Parses first JSON value in a file, returns NULL in case of error */
JSON_Value * json_parse_file(const char *filename); JSON_Value *json_parse_file(const char *filename);
/* Parses first JSON value in a file and ignores comments (/ * * / and //), /* Parses first JSON value in a file and ignores comments (/ * * / and //),
returns NULL in case of error */ returns NULL in case of error */
JSON_Value * json_parse_file_with_comments(const char *filename); JSON_Value *json_parse_file_with_comments(const char *filename);
/* Parses first JSON value in a string, returns NULL in case of error */ /* Parses first JSON value in a string, returns NULL in case of error */
JSON_Value * json_parse_string(const char *string); JSON_Value *json_parse_string(const char *string);
/* Parses first JSON value in a string and ignores comments (/ * * / and //), /* Parses first JSON value in a string and ignores comments (/ * * / and //),
returns NULL in case of error */ returns NULL in case of error */
JSON_Value * json_parse_string_with_comments(const char *string); JSON_Value *json_parse_string_with_comments(const char *string);
/* Serialization */ /* Serialization */
size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */ size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename); JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
char * json_serialize_to_string(const JSON_Value *value); char *json_serialize_to_string(const JSON_Value *value);
/* Pretty serialization */ /* Pretty serialization */
size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */ size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename); JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
char * json_serialize_to_string_pretty(const JSON_Value *value); char *json_serialize_to_string_pretty(const JSON_Value *value);
void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */ void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
/* Comparing */ /* Comparing */
int json_value_equals(const JSON_Value *a, const JSON_Value *b); int json_value_equals(const JSON_Value *a, const JSON_Value *b);
/* Validation /* Validation
This is *NOT* JSON Schema. It validates json by checking if object have identically This is *NOT* JSON Schema. It validates json by checking if object have identically
@ -126,45 +125,45 @@ JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
/* /*
* JSON Object * JSON Object
*/ */
JSON_Value * json_object_get_value (const JSON_Object *object, const char *name); JSON_Value *json_object_get_value(const JSON_Object *object, const char *name);
const char * json_object_get_string (const JSON_Object *object, const char *name); const char *json_object_get_string(const JSON_Object *object, const char *name);
size_t json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ size_t json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); JSON_Object *json_object_get_object(const JSON_Object *object, const char *name);
JSON_Array * json_object_get_array (const JSON_Object *object, const char *name); JSON_Array *json_object_get_array(const JSON_Object *object, const char *name);
double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ double json_object_get_number(const JSON_Object *object, const char *name); /* returns 0 on fail */
int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
/* dotget functions enable addressing values with dot notation in nested objects, /* dotget functions enable addressing values with dot notation in nested objects,
just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
Because valid names in JSON can contain dots, some values may be inaccessible Because valid names in JSON can contain dots, some values may be inaccessible
this way. */ this way. */
JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name); JSON_Value *json_object_dotget_value(const JSON_Object *object, const char *name);
const char * json_object_dotget_string (const JSON_Object *object, const char *name); const char *json_object_dotget_string(const JSON_Object *object, const char *name);
size_t json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ size_t json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); JSON_Object *json_object_dotget_object(const JSON_Object *object, const char *name);
JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name); JSON_Array *json_object_dotget_array(const JSON_Object *object, const char *name);
double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ double json_object_dotget_number(const JSON_Object *object, const char *name); /* returns 0 on fail */
int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
/* Functions to get available names */ /* Functions to get available names */
size_t json_object_get_count (const JSON_Object *object); size_t json_object_get_count(const JSON_Object *object);
const char * json_object_get_name (const JSON_Object *object, size_t index); const char *json_object_get_name(const JSON_Object *object, size_t index);
JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index); JSON_Value *json_object_get_value_at(const JSON_Object *object, size_t index);
JSON_Value * json_object_get_wrapping_value(const JSON_Object *object); JSON_Value *json_object_get_wrapping_value(const JSON_Object *object);
/* Functions to check if object has a value with a specific name. Returned value is 1 if object has /* Functions to check if object has a value with a specific name. Returned value is 1 if object has
* a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */ * a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */
int json_object_has_value (const JSON_Object *object, const char *name); int json_object_has_value(const JSON_Object *object, const char *name);
int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
int json_object_dothas_value (const JSON_Object *object, const char *name); int json_object_dothas_value(const JSON_Object *object, const char *name);
int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
/* Creates new name-value pair or frees and replaces old value with a new one. /* Creates new name-value pair or frees and replaces old value with a new one.
* json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */ * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value); JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string); JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */ JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number); JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean); JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
JSON_Status json_object_set_null(JSON_Object *object, const char *name); JSON_Status json_object_set_null(JSON_Object *object, const char *name);
@ -190,15 +189,15 @@ JSON_Status json_object_clear(JSON_Object *object);
/* /*
*JSON Array *JSON Array
*/ */
JSON_Value * json_array_get_value (const JSON_Array *array, size_t index); JSON_Value *json_array_get_value(const JSON_Array *array, size_t index);
const char * json_array_get_string (const JSON_Array *array, size_t index); const char *json_array_get_string(const JSON_Array *array, size_t index);
size_t json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */ size_t json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */
JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); JSON_Object *json_array_get_object(const JSON_Array *array, size_t index);
JSON_Array * json_array_get_array (const JSON_Array *array, size_t index); JSON_Array *json_array_get_array(const JSON_Array *array, size_t index);
double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */ double json_array_get_number(const JSON_Array *array, size_t index); /* returns 0 on fail */
int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */ int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
size_t json_array_get_count (const JSON_Array *array); size_t json_array_get_count(const JSON_Array *array);
JSON_Value * json_array_get_wrapping_value(const JSON_Array *array); JSON_Value *json_array_get_wrapping_value(const JSON_Array *array);
/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist. /* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
* Order of values in array may change during execution. */ * Order of values in array may change during execution. */
@ -208,7 +207,7 @@ JSON_Status json_array_remove(JSON_Array *array, size_t i);
* Does nothing and returns JSONFailure if index doesn't exist. * Does nothing and returns JSONFailure if index doesn't exist.
* json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */ * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value); JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string); JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char *string);
JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */ JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number); JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean); JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
@ -229,33 +228,33 @@ JSON_Status json_array_append_null(JSON_Array *array);
/* /*
*JSON Value *JSON Value
*/ */
JSON_Value * json_value_init_object (void); JSON_Value *json_value_init_object(void);
JSON_Value * json_value_init_array (void); JSON_Value *json_value_init_array(void);
JSON_Value * json_value_init_string (const char *string); /* copies passed string */ JSON_Value *json_value_init_string(const char *string); /* copies passed string */
JSON_Value * json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */ JSON_Value *json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */
JSON_Value * json_value_init_number (double number); JSON_Value *json_value_init_number(double number);
JSON_Value * json_value_init_boolean(int boolean); JSON_Value *json_value_init_boolean(int boolean);
JSON_Value * json_value_init_null (void); JSON_Value *json_value_init_null(void);
JSON_Value * json_value_deep_copy (const JSON_Value *value); JSON_Value *json_value_deep_copy(const JSON_Value *value);
void json_value_free (JSON_Value *value); void json_value_free(JSON_Value *value);
JSON_Value_Type json_value_get_type (const JSON_Value *value); JSON_Value_Type json_value_get_type(const JSON_Value *value);
JSON_Object * json_value_get_object (const JSON_Value *value); JSON_Object *json_value_get_object(const JSON_Value *value);
JSON_Array * json_value_get_array (const JSON_Value *value); JSON_Array *json_value_get_array(const JSON_Value *value);
const char * json_value_get_string (const JSON_Value *value); const char *json_value_get_string(const JSON_Value *value);
size_t json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */ size_t json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */
double json_value_get_number (const JSON_Value *value); double json_value_get_number(const JSON_Value *value);
int json_value_get_boolean(const JSON_Value *value); int json_value_get_boolean(const JSON_Value *value);
JSON_Value * json_value_get_parent (const JSON_Value *value); JSON_Value *json_value_get_parent(const JSON_Value *value);
/* Same as above, but shorter */ /* Same as above, but shorter */
JSON_Value_Type json_type (const JSON_Value *value); JSON_Value_Type json_type(const JSON_Value *value);
JSON_Object * json_object (const JSON_Value *value); JSON_Object *json_object(const JSON_Value *value);
JSON_Array * json_array (const JSON_Value *value); JSON_Array *json_array(const JSON_Value *value);
const char * json_string (const JSON_Value *value); const char *json_string(const JSON_Value *value);
size_t json_string_len(const JSON_Value *value); /* doesn't account for last null character */ size_t json_string_len(const JSON_Value *value); /* doesn't account for last null character */
double json_number (const JSON_Value *value); double json_number(const JSON_Value *value);
int json_boolean(const JSON_Value *value); int json_boolean(const JSON_Value *value);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,58 +1,48 @@
#include "particle.h" #include "particle.h"
#include "stb_ds.h" #include "stb_ds.h"
struct emitter make_emitter() struct emitter make_emitter() {
{ struct emitter e = {0};
struct emitter e = { 0 }; return e;
return e;
} }
struct emitter set_emitter(struct emitter e) struct emitter set_emitter(struct emitter e) {
{ arrsetlen(e.particles, e.max);
arrsetlen(e.particles, e.max);
e.first = &e.particles[0]; e.first = &e.particles[0];
for (int i = 0; i < arrlen(e.particles)-1; i++) { for (int i = 0; i < arrlen(e.particles) - 1; i++) {
e.particles[i].next = &e.particles[i+1]; e.particles[i].next = &e.particles[i + 1];
} }
return e; return e;
} }
void free_emitter(struct emitter e) void free_emitter(struct emitter e) {
{ arrfree(e.particles);
arrfree(e.particles); }
}
void start_emitter(struct emitter e) {
void start_emitter(struct emitter e) }
{
void pause_emitter(struct emitter e) {
} }
void pause_emitter(struct emitter e) void stop_emitter(struct emitter e) {
{ }
} void emitter_step(struct emitter e, double dt) {
for (int i = 0; i < arrlen(e.particles); i++) {
void stop_emitter(struct emitter e) if (e.particles[i].life <= 0)
{ continue;
} e.particles[i].pos = cpvadd(e.particles[i].pos, cpvmult(e.particles[i].v, dt));
e.particles[i].angle += e.particles[i].av * dt;
void emitter_step(struct emitter e, double dt) e.particles[i].life -= dt;
{
for (int i = 0; i < arrlen(e.particles); i++) { if (e.particles[i].life <= 0) {
if (e.particles[i].life <= 0) e.particles[i].next = e.first;
continue; e.first = &e.particles[i];
e.particles[i].pos = cpvadd(e.particles[i].pos, cpvmult(e.particles[i].v, dt));
e.particles[i].angle += e.particles[i].av * dt;
e.particles[i].life -= dt;
if (e.particles[i].life <= 0) {
e.particles[i].next = e.first;
e.first = &e.particles[i];
}
} }
}
} }

View file

@ -1,17 +1,17 @@
#include "resources.h" #include "resources.h"
#include "config.h" #include "config.h"
#include <dirent.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "vec.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "log.h" #include "log.h"
#include "vec.h"
#include <dirent.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <ftw.h> #include <ftw.h>
@ -31,111 +31,101 @@ static const char *cur_ext = NULL;
struct dirent *c_dirent = NULL; struct dirent *c_dirent = NULL;
struct vec *c_vec = NULL; struct vec *c_vec = NULL;
char pathbuf[MAXPATH+1]; char pathbuf[MAXPATH + 1];
void resources_init() void resources_init() {
{ prefabs = vec_make(MAXNAME, 25);
prefabs = vec_make(MAXNAME, 25);
DATA_PATH = malloc(MAXPATH); DATA_PATH = malloc(MAXPATH);
getcwd(DATA_PATH, MAXPATH); getcwd(DATA_PATH, MAXPATH);
strncat(DATA_PATH, "/", MAXPATH); strncat(DATA_PATH, "/", MAXPATH);
if (!PREF_PATH) if (!PREF_PATH)
PREF_PATH = strdup("./tmp/"); PREF_PATH = strdup("./tmp/");
} }
char *get_filename_from_path(char *path, int extension) char *get_filename_from_path(char *path, int extension) {
{ char *dirpos = strrchr(path, '/');
char *dirpos = strrchr(path, '/'); if (!dirpos)
if (!dirpos) dirpos = path;
dirpos = path;
char *end = strrchr(path, '\0'); char *end = strrchr(path, '\0');
int offset = 0; int offset = 0;
if (!extension) { if (!extension) {
char *ext = strrchr(path, '.'); char *ext = strrchr(path, '.');
offset = end - ext; offset = end - ext;
YughInfo("Making %s without extension ..."); YughInfo("Making %s without extension ...");
} }
char *filename = malloc(sizeof(char) * (end - dirpos - offset + 1)); char *filename = malloc(sizeof(char) * (end - dirpos - offset + 1));
strncpy(filename, dirpos, end - dirpos - offset); strncpy(filename, dirpos, end - dirpos - offset);
return filename; return filename;
} }
char *get_directory_from_path(char *path) char *get_directory_from_path(char *path) {
{ const char *dirpos = strrchr(path, '/');
const char *dirpos = strrchr(path, '/'); char *directory = (char *)malloc(sizeof(char) * (dirpos - path + 1));
char *directory = (char *) malloc(sizeof(char) * (dirpos - path + 1)); strncpy(directory, path, dirpos - path);
strncpy(directory, path, dirpos - path); return directory;
return directory;
} }
FILE *res_open(char *path, const char *tag) FILE *res_open(char *path, const char *tag) {
{ strncpy(pathbuf, DATA_PATH, MAXPATH);
strncpy(pathbuf, DATA_PATH, MAXPATH); strncat(pathbuf, path, MAXPATH);
strncat(pathbuf, path, MAXPATH); FILE *f = fopen(pathbuf, tag);
FILE *f = fopen(pathbuf, tag); return f;
return f;
} }
static int ext_check(const char *path, const struct stat *sb, int typeflag) static int ext_check(const char *path, const struct stat *sb, int typeflag) {
{ if (typeflag == FTW_F) {
if (typeflag == FTW_F) { const char *ext = strrchr(path, '.');
const char *ext = strrchr(path, '.'); if (ext != NULL && !strcmp(ext, cur_ext))
if (ext != NULL && !strcmp(ext, cur_ext)) vec_add(c_vec, path);
vec_add(c_vec, path); }
}
return 0; return 0;
} }
void fill_extensions(struct vec *vec, const char *path, const char *ext) void fill_extensions(struct vec *vec, const char *path, const char *ext) {
{ c_vec = vec;
c_vec = vec; cur_ext = ext;
cur_ext = ext; vec_clear(c_vec);
vec_clear(c_vec); ftw(".", ext_check, 10);
ftw(".", ext_check, 10);
} }
void findPrefabs() void findPrefabs() {
{ fill_extensions(prefabs, DATA_PATH, EXT_PREFAB);
fill_extensions(prefabs, DATA_PATH, EXT_PREFAB);
} }
char *str_replace_ext(const char *s, const char *newext) { char *str_replace_ext(const char *s, const char *newext) {
static char ret[256]; static char ret[256];
strncpy(ret, s, 256); strncpy(ret, s, 256);
char *ext = strrchr(ret, '.'); char *ext = strrchr(ret, '.');
strncpy(ext, newext, 10); strncpy(ext, newext, 10);
return ret; return ret;
} }
FILE *path_open(const char *tag, const char *fmt, ...) FILE *path_open(const char *tag, const char *fmt, ...) {
{ va_list args;
va_list args; va_start(args, fmt);
va_start(args, fmt); vsprintf(pathbuf, fmt, args);
vsprintf(pathbuf, fmt, args); va_end(args);
va_end(args);
FILE *f = fopen(pathbuf, tag); FILE *f = fopen(pathbuf, tag);
return f; return f;
} }
char *make_path(const char *file) char *make_path(const char *file) {
{ strncpy(pathbuf, DATA_PATH, MAXPATH);
strncpy(pathbuf, DATA_PATH, MAXPATH); strncat(pathbuf, file, MAXPATH);
strncat(pathbuf, file, MAXPATH); return pathbuf;
return pathbuf;
} }
char *strdup(const char *s) char *strdup(const char *s) {
{ char *new = malloc(sizeof(char) * (strlen(s) + 1));
char *new = malloc(sizeof(char)*(strlen(s)+1)); strcpy(new, s);
strcpy(new, s); return new;
return new;
} }

View file

@ -1,8 +1,6 @@
#ifndef RESOURCES_H #ifndef RESOURCES_H
#define RESOURCES_H #define RESOURCES_H
#include <stdio.h> #include <stdio.h>
struct vec; struct vec;

View file

@ -1,7 +1,7 @@
#include "script.h" #include "script.h"
#include "stdio.h"
#include "log.h" #include "log.h"
#include "stdio.h"
#include "ffi.h" #include "ffi.h"
#include "font.h" #include "font.h"
@ -10,39 +10,38 @@
#include "stb_ds.h" #include "stb_ds.h"
#include "time.h"
#include "sys/stat.h" #include "sys/stat.h"
#include "sys/types.h" #include "sys/types.h"
#include "time.h"
JSContext *js = NULL; JSContext *js = NULL;
JSRuntime *rt = NULL; JSRuntime *rt = NULL;
static int load_prefab(const char *fpath, const struct stat *sb, int typeflag) { static int load_prefab(const char *fpath, const struct stat *sb, int typeflag) {
if (typeflag != FTW_F) if (typeflag != FTW_F)
return 0;
if (!strcmp(".prefab", strrchr(fpath, '.')))
script_dofile(fpath);
return 0; return 0;
if (!strcmp(".prefab", strrchr(fpath, '.')))
script_dofile(fpath);
return 0;
} }
void script_startup() void script_startup() {
{ rt = JS_NewRuntime();
rt = JS_NewRuntime(); JS_SetMaxStackSize(rt, 0);
JS_SetMaxStackSize(rt,0); js = JS_NewContext(rt);
js = JS_NewContext(rt); ffi_load();
ffi_load();
} }
JSValue num_cache[100] = {0}; JSValue num_cache[100] = {0};
void script_init() { void script_init() {
/* Load all prefabs into memory */ /* Load all prefabs into memory */
script_dofile("scripts/engine.js"); script_dofile("scripts/engine.js");
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
num_cache[i] = int2js(i); num_cache[i] = int2js(i);
} }
void script_run(const char *script) { void script_run(const char *script) {
@ -52,72 +51,68 @@ void script_run(const char *script) {
struct callee stacktrace_callee; struct callee stacktrace_callee;
time_t file_mod_secs(const char *file) { time_t file_mod_secs(const char *file) {
struct stat attr; struct stat attr;
stat(file, &attr); stat(file, &attr);
return attr.st_mtime; return attr.st_mtime;
} }
void js_stacktrace() void js_stacktrace() {
{
call_callee(&stacktrace_callee); call_callee(&stacktrace_callee);
return; return;
} }
void js_dump_stack() void js_dump_stack() {
{
js_stacktrace(); js_stacktrace();
return; return;
JSValue exception = JS_GetException(js); JSValue exception = JS_GetException(js);
if (JS_IsNull(exception)) return; if (JS_IsNull(exception)) return;
JSValue val = JS_GetPropertyStr(js, exception, "stack"); JSValue val = JS_GetPropertyStr(js, exception, "stack");
if (!JS_IsUndefined(val)) { if (!JS_IsUndefined(val)) {
const char *name = JS_ToCString(js, JS_GetPropertyStr(js, exception, "name")); const char *name = JS_ToCString(js, JS_GetPropertyStr(js, exception, "name"));
const char *msg = JS_ToCString(js, JS_GetPropertyStr(js, exception, "message")); const char *msg = JS_ToCString(js, JS_GetPropertyStr(js, exception, "message"));
const char *stack = JS_ToCString(js, val); const char *stack = JS_ToCString(js, val);
YughError("%s :: %s\n%s", name, msg, stack); YughError("%s :: %s\n%s", name, msg, stack);
JS_FreeCString(js, name); JS_FreeCString(js, name);
JS_FreeCString(js, msg); JS_FreeCString(js, msg);
JS_FreeCString(js, stack); JS_FreeCString(js, stack);
} }
} }
int js_print_exception(JSValue v) {
if (JS_IsException(v)) {
JSValue exception = JS_GetException(js);
JSValue val = JS_GetPropertyStr(js, exception, "stack");
if (!JS_IsUndefined(val)) {
const char *name = JS_ToCString(js, JS_GetPropertyStr(js, exception, "name"));
const char *msg = JS_ToCString(js, JS_GetPropertyStr(js, exception, "message"));
const char *stack = JS_ToCString(js, val);
YughWarn("%s :: %s\n%s", name, msg, stack);
int js_print_exception(JSValue v) JS_FreeCString(js, name);
{ JS_FreeCString(js, msg);
if (JS_IsException(v)) { JS_FreeCString(js, stack);
JSValue exception = JS_GetException(js); }
JSValue val = JS_GetPropertyStr(js, exception, "stack");
if (!JS_IsUndefined(val)) {
const char *name = JS_ToCString(js, JS_GetPropertyStr(js, exception, "name"));
const char *msg = JS_ToCString(js, JS_GetPropertyStr(js, exception, "message"));
const char *stack = JS_ToCString(js, val);
YughWarn("%s :: %s\n%s", name, msg, stack);
JS_FreeCString(js, name); return 1;
JS_FreeCString(js, msg); }
JS_FreeCString(js, stack);
} return 0;
return 1;
}
return 0;
} }
int script_dofile(const char *file) { int script_dofile(const char *file) {
YughInfo("Doing script %s", file); YughInfo("Doing script %s", file);
const char *script = slurp_text(file); const char *script = slurp_text(file);
if (!script) { if (!script) {
YughError("Can't find file %s.", file); YughError("Can't find file %s.", file);
return 0; return 0;
} }
JSValue obj = JS_Eval(js, script, strlen(script), file, 0); JSValue obj = JS_Eval(js, script, strlen(script), file, 0);
js_print_exception(obj); js_print_exception(obj);
JS_FreeValue(js, obj); JS_FreeValue(js, obj);
return file_mod_secs(file); return file_mod_secs(file);
} }
/* env is an object in the scripting environment; /* env is an object in the scripting environment;
@ -129,17 +124,14 @@ void script_eval_w_env(const char *s, JSValue env) {
JS_FreeValue(js, v); JS_FreeValue(js, v);
} }
void script_call_sym(JSValue sym) void script_call_sym(JSValue sym) {
{
struct callee c; struct callee c;
c.fn = sym; c.fn = sym;
c.obj = JS_GetGlobalObject(js); c.obj = JS_GetGlobalObject(js);
call_callee(&c); call_callee(&c);
} }
JSValue js_callee_exec(struct callee *c, int argc, JSValue *argv) {
JSValue js_callee_exec(struct callee *c, int argc, JSValue *argv)
{
JSValue ret = JS_Call(js, c->fn, c->obj, argc, argv); JSValue ret = JS_Call(js, c->fn, c->obj, argc, argv);
js_print_exception(ret); js_print_exception(ret);
JS_FreeValue(js, ret); JS_FreeValue(js, ret);
@ -150,29 +142,25 @@ void call_callee(struct callee *c) {
js_callee_exec(c, 0, NULL); js_callee_exec(c, 0, NULL);
} }
void callee_dbl(struct callee c, double d) void callee_dbl(struct callee c, double d) {
{
JSValue v = num2js(d); JSValue v = num2js(d);
js_callee_exec(&c, 1, &v); js_callee_exec(&c, 1, &v);
JS_FreeValue(js, v); JS_FreeValue(js, v);
} }
void callee_int(struct callee c, int i) void callee_int(struct callee c, int i) {
{
JSValue v = int2js(i); JSValue v = int2js(i);
js_callee_exec(&c, 1, &v); js_callee_exec(&c, 1, &v);
JS_FreeValue(js, v); JS_FreeValue(js, v);
} }
void callee_vec2(struct callee c, cpVect vec) void callee_vec2(struct callee c, cpVect vec) {
{
JSValue v = vec2js(vec); JSValue v = vec2js(vec);
js_callee_exec(&c, 1, &v); js_callee_exec(&c, 1, &v);
JS_FreeValue(js, v); JS_FreeValue(js, v);
} }
void script_callee(struct callee c, int argc, JSValue *argv) void script_callee(struct callee c, int argc, JSValue *argv) {
{
js_callee_exec(&c, argc, argv); js_callee_exec(&c, argc, argv);
} }
@ -193,7 +181,7 @@ void register_nk_gui(struct callee c) { nk_gui_callee = c; }
void call_nk_gui() { js_callee_exec(&nk_gui_callee, 0, NULL); } void call_nk_gui() { js_callee_exec(&nk_gui_callee, 0, NULL); }
static struct callee physupdate_callee; static struct callee physupdate_callee;
void register_physics(struct callee c) { physupdate_callee = c;} void register_physics(struct callee c) { physupdate_callee = c; }
void call_physics(double dt) { callee_dbl(physupdate_callee, dt); } void call_physics(double dt) { callee_dbl(physupdate_callee, dt); }
struct callee debug_callee; struct callee debug_callee;

View file

@ -1,15 +1,15 @@
#include "shader.h" #include "shader.h"
#include "render.h"
#include "config.h" #include "config.h"
#include <stdio.h> #include "font.h"
#include <string.h>
#include <stdlib.h>
#include "log.h" #include "log.h"
#include "render.h"
#include "resources.h" #include "resources.h"
#include "stb_ds.h" #include "stb_ds.h"
#include "timer.h" #include "timer.h"
#include "font.h" #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "time.h" #include "time.h"
@ -17,110 +17,104 @@
static struct shader *shaders; static struct shader *shaders;
struct shader *MakeShader(const char *vertpath, const char *fragpath) struct shader *MakeShader(const char *vertpath, const char *fragpath) {
{ if (arrcap(shaders) == 0)
if (arrcap(shaders) == 0) arrsetcap(shaders, 20);
arrsetcap(shaders, 20);
struct shader init = { struct shader init = {
.vertpath = vertpath, .vertpath = vertpath,
.fragpath = fragpath }; .fragpath = fragpath};
shader_compile(&init); shader_compile(&init);
arrput(shaders, init); arrput(shaders, init);
return &arrlast(shaders); return &arrlast(shaders);
} }
int shader_compile_error(int shader) int shader_compile_error(int shader) {
{ /*
/* GLint success = 0;
GLint success = 0; GLchar infoLog[ERROR_BUFFER] = { '\0' };
GLchar infoLog[ERROR_BUFFER] = { '\0' };
glGetShaderiv(shader, GL_COMPILE_STATUS, &success); glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (success) return 0; if (success) return 0;
glGetShaderInfoLog(shader, ERROR_BUFFER, NULL, infoLog); glGetShaderInfoLog(shader, ERROR_BUFFER, NULL, infoLog);
YughLog(0, LOG_ERROR, "Shader compilation error.\nLog: %s", infoLog); YughLog(0, LOG_ERROR, "Shader compilation error.\nLog: %s", infoLog);
return 1; return 1;
*/ */
} }
int shader_link_error(int shader) int shader_link_error(int shader) {
{ /*
/* GLint success = 0;
GLint success = 0; GLchar infoLog[ERROR_BUFFER] = { '\0' };
GLchar infoLog[ERROR_BUFFER] = { '\0' };
glGetProgramiv(shader, GL_LINK_STATUS, &success); glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (success) return 0; if (success) return 0;
glGetProgramInfoLog(shader, ERROR_BUFFER, NULL, infoLog); glGetProgramInfoLog(shader, ERROR_BUFFER, NULL, infoLog);
YughLog(0, LOG_ERROR, "Shader link error.\nLog: %s", infoLog); YughLog(0, LOG_ERROR, "Shader link error.\nLog: %s", infoLog);
return 1; return 1;
*/ */
} }
int load_shader_from_file(const char *path, int type) int load_shader_from_file(const char *path, int type) {
{ char spath[MAXPATH] = {'\0'};
char spath[MAXPATH] = {'\0'};
sprintf(spath, "%s%s", "shaders/", path); sprintf(spath, "%s%s", "shaders/", path);
FILE *f = fopen(make_path(spath), "r'"); FILE *f = fopen(make_path(spath), "r'");
if (!path) if (!path)
perror(spath), exit(1); perror(spath), exit(1);
char *buf; char *buf;
long int fsize; long int fsize;
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
fsize = ftell(f); fsize = ftell(f);
buf = malloc(fsize+1); buf = malloc(fsize + 1);
rewind(f); rewind(f);
size_t r = fread(buf, sizeof(char), fsize, f); size_t r = fread(buf, sizeof(char), fsize, f);
buf[r] = '\0'; buf[r] = '\0';
fclose(f); fclose(f);
/* /*
GLuint id = glCreateShader(type); GLuint id = glCreateShader(type);
const char *code = buf; const char *code = buf;
glShaderSource(id, 1, &code, NULL); glShaderSource(id, 1, &code, NULL);
glCompileShader(id); glCompileShader(id);
if (shader_compile_error(id)) { if (shader_compile_error(id)) {
YughError("Error with shader %s.", path); YughError("Error with shader %s.", path);
return 0; return 0;
} }
free(buf); free(buf);
return id;
*/ return id;
*/
} }
void shader_compile(struct shader *shader) void shader_compile(struct shader *shader) {
{ YughInfo("Making shader with %s and %s.", shader->vertpath, shader->fragpath);
YughInfo("Making shader with %s and %s.", shader->vertpath, shader->fragpath); char spath[MAXPATH];
char spath[MAXPATH]; sprintf(spath, "%s%s", "shaders/", shader->vertpath);
sprintf(spath,"%s%s", "shaders/", shader->vertpath); const char *vsrc = slurp_text(spath);
const char *vsrc = slurp_text(spath); sprintf(spath, "%s%s", "shaders/", shader->fragpath);
sprintf(spath, "%s%s", "shaders/", shader->fragpath); const char *fsrc = slurp_text(spath);
const char *fsrc = slurp_text(spath);
shader->shd = sg_make_shader(&(sg_shader_desc){ shader->shd = sg_make_shader(&(sg_shader_desc){
.vs.source = vsrc, .vs.source = vsrc,
.fs.source = fsrc, .fs.source = fsrc,
.label = shader->vertpath, .label = shader->vertpath,
}); });
free(vsrc); free(vsrc);
free(fsrc); free(fsrc);
} }
void shader_use(struct shader *shader) void shader_use(struct shader *shader) {
{ // glUseProgram(shader->id);
// glUseProgram(shader->id);
} }
/* /*
void shader_setbool(struct shader *shader, const char *name, int val) void shader_setbool(struct shader *shader, const char *name, int val)
@ -171,16 +165,13 @@ void shader_setUBO(struct shader *shader, const char *name, unsigned int index)
*/ */
void shader_compile_all() void shader_compile_all() {
{ for (int i = 0; i < arrlen(shaders); i++)
for (int i = 0; i < arrlen(shaders); i++) shader_compile(&shaders[i]);
shader_compile(&shaders[i]);
} }
void shader_setvec3(struct shader *shader, const char *name, mfloat_t val[3]) void shader_setvec3(struct shader *shader, const char *name, mfloat_t val[3]) {
{ // glUniform3fv(glGetUniformLocation(shader->id, name), 1, val);
// glUniform3fv(glGetUniformLocation(shader->id, name), 1, val);
} }
void shader_setmat4(struct shader *shader, const char *name, mfloat_t val[16]) void shader_setmat4(struct shader *shader, const char *name, mfloat_t val[16]) {
{ // glUniformMatrix4fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE, val);
// glUniformMatrix4fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE, val);
} }

View file

@ -5,9 +5,9 @@
#include "sokol/sokol_gfx.h" #include "sokol/sokol_gfx.h"
struct shader { struct shader {
sg_shader shd; sg_shader shd;
const char *vertpath; const char *vertpath;
const char *fragpath; const char *fragpath;
}; };
void shader_compile_all(); void shader_compile_all();

View file

@ -1,20 +1,20 @@
#include "sound.h" #include "sound.h"
#include "resources.h"
#include <stdlib.h>
#include "log.h"
#include "string.h"
#include "math.h"
#include "limits.h" #include "limits.h"
#include "time.h" #include "log.h"
#include "math.h"
#include "music.h" #include "music.h"
#include "resources.h"
#include "stb_vorbis.h" #include "stb_vorbis.h"
#include "string.h"
#include "time.h"
#include <stdlib.h>
#include "samplerate.h" #include "samplerate.h"
#include "stb_ds.h" #include "stb_ds.h"
#include "mix.h"
#include "dsp.h" #include "dsp.h"
#include "mix.h"
#include "miniaudio.h" #include "miniaudio.h"
@ -25,85 +25,81 @@
#include "tml.h" #include "tml.h"
static struct { static struct {
char *key; char *key;
struct wav *value; struct wav *value;
} *wavhash = NULL; } *wavhash = NULL;
static struct wav change_channels(struct wav w, int ch) static struct wav change_channels(struct wav w, int ch) {
{ short *data = w.data;
short *data = w.data; int samples = ch * w.frames;
int samples = ch * w.frames; short *new = malloc(sizeof(short) * samples);
short *new = malloc(sizeof(short)*samples);
if (ch > w.ch) { if (ch > w.ch) {
/* Sets all new channels equal to the first one */ /* Sets all new channels equal to the first one */
for (int i = 0; i < w.frames; i++) { for (int i = 0; i < w.frames; i++) {
for (int j = 0; j < ch; j++) for (int j = 0; j < ch; j++)
new[i*ch+j] = data[i]; new[i * ch + j] = data[i];
}
} else {
/* Simple method; just use first N channels present in wav */
for (int i = 0; i < w.frames; i++)
for (int j = 0; j < ch; j++)
new[i*ch+j] = data[i*ch+j];
} }
} else {
/* Simple method; just use first N channels present in wav */
for (int i = 0; i < w.frames; i++)
for (int j = 0; j < ch; j++)
new[i * ch + j] = data[i * ch + j];
}
free (w.data); free(w.data);
w.data = new; w.data = new;
return w; return w;
} }
static struct wav change_samplerate(struct wav w, int rate) static struct wav change_samplerate(struct wav w, int rate) {
{ float ratio = (float)rate / w.samplerate;
float ratio = (float)rate/w.samplerate; int outframes = w.frames * ratio;
int outframes = w.frames * ratio; SRC_DATA ssrc;
SRC_DATA ssrc; float floatdata[w.frames * w.ch];
float floatdata[w.frames*w.ch]; src_short_to_float_array(w.data, floatdata, w.frames * w.ch);
src_short_to_float_array(w.data, floatdata, w.frames*w.ch); float resampled[w.ch * outframes];
float resampled[w.ch*outframes];
ssrc.data_in = floatdata; ssrc.data_in = floatdata;
ssrc.data_out = resampled; ssrc.data_out = resampled;
ssrc.input_frames = w.frames; ssrc.input_frames = w.frames;
ssrc.output_frames = outframes; ssrc.output_frames = outframes;
ssrc.src_ratio = ratio; ssrc.src_ratio = ratio;
src_simple(&ssrc, SRC_SINC_BEST_QUALITY, w.ch); src_simple(&ssrc, SRC_SINC_BEST_QUALITY, w.ch);
short *newdata = malloc(sizeof(short)*outframes*w.ch); short *newdata = malloc(sizeof(short) * outframes * w.ch);
src_float_to_short_array(resampled, newdata, outframes*w.ch); src_float_to_short_array(resampled, newdata, outframes * w.ch);
free(w.data); free(w.data);
w.data = newdata; w.data = newdata;
w.samplerate = rate; w.samplerate = rate;
return w; return w;
} }
void wav_norm_gain(struct wav *w, double lv) void wav_norm_gain(struct wav *w, double lv) {
{ short tarmax = db2short(lv);
short tarmax = db2short(lv); short max = 0;
short max = 0; short *s = w->data;
short *s = w->data; for (int i = 0; i < w->frames; i++) {
for (int i = 0; i < w->frames; i++) { for (int j = 0; j < w->ch; j++) {
for (int j = 0; j < w->ch; j++) { max = (abs(s[i * w->ch + j]) > max) ? abs(s[i * w->ch + j]) : max;
max = (abs(s[i*w->ch + j]) > max) ? abs(s[i*w->ch + j]) : max;
}
} }
}
float mult = (float)max / tarmax; float mult = (float)max / tarmax;
for (int i = 0; i < w->frames; i++) { for (int i = 0; i < w->frames; i++) {
for (int j = 0; j < w->ch; j++) { for (int j = 0; j < w->ch; j++) {
s[i*w->ch + j] *= mult; s[i * w->ch + j] *= mult;
}
} }
}
} }
static ma_engine *engine; static ma_engine *engine;
void sound_init() void sound_init() {
{
ma_result result; ma_result result;
engine = malloc(sizeof(*engine)); engine = malloc(sizeof(*engine));
result = ma_engine_init(NULL, engine); result = ma_engine_init(NULL, engine);
@ -111,66 +107,61 @@ void sound_init()
return; return;
} }
return; return;
mixer_init(); mixer_init();
} }
struct wav *make_sound(const char *wav) struct wav *make_sound(const char *wav) {
{ int index = shgeti(wavhash, wav);
int index = shgeti(wavhash, wav); if (index != -1) return wavhash[index].value;
if (index != -1) return wavhash[index].value;
struct wav mwav; struct wav mwav;
// mwav.data = drwav_open_file_and_read_pcm_frames_s16(wav, &mwav.ch, &mwav.samplerate, &mwav.frames, NULL); // mwav.data = drwav_open_file_and_read_pcm_frames_s16(wav, &mwav.ch, &mwav.samplerate, &mwav.frames, NULL);
if (mwav.samplerate != SAMPLERATE) { if (mwav.samplerate != SAMPLERATE) {
YughInfo("Changing samplerate of %s from %d to %d.", wav, mwav.samplerate, SAMPLERATE); YughInfo("Changing samplerate of %s from %d to %d.", wav, mwav.samplerate, SAMPLERATE);
// mwav = change_samplerate(mwav, SAMPLERATE); // mwav = change_samplerate(mwav, SAMPLERATE);
} }
if (mwav.ch != CHANNELS) { if (mwav.ch != CHANNELS) {
YughInfo("Changing channels of %s from %d to %d.", wav, mwav.ch, CHANNELS); YughInfo("Changing channels of %s from %d to %d.", wav, mwav.ch, CHANNELS);
mwav = change_channels(mwav, CHANNELS); mwav = change_channels(mwav, CHANNELS);
} }
mwav.gain = 1.f; mwav.gain = 1.f;
struct wav *newwav = malloc(sizeof(*newwav)); struct wav *newwav = malloc(sizeof(*newwav));
*newwav = mwav; *newwav = mwav;
if (shlen(wavhash) == 0) sh_new_arena(wavhash); if (shlen(wavhash) == 0) sh_new_arena(wavhash);
shput(wavhash, wav, newwav); shput(wavhash, wav, newwav);
return newwav; return newwav;
} }
void free_sound(const char *wav) void free_sound(const char *wav) {
{ struct wav *w = shget(wavhash, wav);
struct wav *w = shget(wavhash, wav); if (w == NULL) return;
if (w == NULL) return;
free(w->data); free(w->data);
free(w); free(w);
shdel(wavhash, wav); shdel(wavhash, wav);
} }
struct soundstream *soundstream_make() struct soundstream *soundstream_make() {
{ struct soundstream *new = malloc(sizeof(*new));
struct soundstream *new = malloc(sizeof(*new)); new->buf = circbuf_make(sizeof(short), BUF_FRAMES * CHANNELS * 2);
new->buf = circbuf_make(sizeof(short), BUF_FRAMES*CHANNELS*2); return new;
return new;
} }
void mini_sound(char *path) void mini_sound(char *path) {
{
ma_engine_play_sound(engine, path, NULL); ma_engine_play_sound(engine, path, NULL);
} }
static ma_sound music_sound; static ma_sound music_sound;
void mini_music_play(char *path) void mini_music_play(char *path) {
{
ma_sound_uninit(&music_sound); ma_sound_uninit(&music_sound);
int result = ma_sound_init_from_file(engine, path, MA_SOUND_FLAG_NO_SPATIALIZATION, NULL, NULL, &music_sound); int result = ma_sound_init_from_file(engine, path, MA_SOUND_FLAG_NO_SPATIALIZATION, NULL, NULL, &music_sound);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
@ -181,163 +172,139 @@ void mini_music_play(char *path)
ma_sound_start(&music_sound); ma_sound_start(&music_sound);
} }
void mini_music_pause() void mini_music_pause() {
{
ma_sound_stop(&music_sound); ma_sound_stop(&music_sound);
} }
void mini_music_stop() void mini_music_stop() {
{
ma_sound_stop(&music_sound); ma_sound_stop(&music_sound);
} }
void mini_master(float v) void mini_master(float v) {
{
ma_engine_set_volume(engine, v); ma_engine_set_volume(engine, v);
} }
void kill_oneshot(struct sound *s) void kill_oneshot(struct sound *s) {
{ free(s);
free(s);
} }
void play_oneshot(struct wav *wav) { void play_oneshot(struct wav *wav) {
struct sound *new = malloc(sizeof(*new)); struct sound *new = malloc(sizeof(*new));
new->data = wav; new->data = wav;
new->bus = first_free_bus(dsp_filter(new, sound_fillbuf)); new->bus = first_free_bus(dsp_filter(new, sound_fillbuf));
new->playing=1; new->playing = 1;
new->loop=0; new->loop = 0;
new->frame = 0; new->frame = 0;
new->endcb = kill_oneshot; new->endcb = kill_oneshot;
} }
struct sound *play_sound(struct wav *wav) struct sound *play_sound(struct wav *wav) {
{ struct sound *new = calloc(1, sizeof(*new));
struct sound *new = calloc(1, sizeof(*new)); new->data = wav;
new->data = wav;
new->bus = first_free_bus(dsp_filter(new, sound_fillbuf)); new->bus = first_free_bus(dsp_filter(new, sound_fillbuf));
new->playing = 1; new->playing = 1;
return new; return new;
} }
int sound_playing(const struct sound *s) int sound_playing(const struct sound *s) {
{ return s->playing;
return s->playing;
} }
int sound_paused(const struct sound *s) int sound_paused(const struct sound *s) {
{ return (!s->playing && s->frame < s->data->frames);
return (!s->playing && s->frame < s->data->frames);
} }
void sound_pause(struct sound *s) void sound_pause(struct sound *s) {
{ s->playing = 0;
s->playing = 0; bus_free(s->bus);
bus_free(s->bus);
} }
void sound_resume(struct sound *s) void sound_resume(struct sound *s) {
{ s->playing = 1;
s->playing = 1; s->bus = first_free_bus(dsp_filter(s, sound_fillbuf));
s->bus = first_free_bus(dsp_filter(s, sound_fillbuf));
} }
void sound_stop(struct sound *s) void sound_stop(struct sound *s) {
{ s->playing = 0;
s->playing = 0; s->frame = 0;
s->frame = 0; bus_free(s->bus);
bus_free(s->bus);
} }
int sound_finished(const struct sound *s) int sound_finished(const struct sound *s) {
{ return !s->playing && s->frame == s->data->frames;
return !s->playing && s->frame == s->data->frames;
} }
int sound_stopped(const struct sound *s) int sound_stopped(const struct sound *s) {
{ return !s->playing && s->frame == 0;
return !s->playing && s->frame == 0;
} }
struct mp3 make_music(const char *mp3) struct mp3 make_music(const char *mp3) {
{ // drmp3 new;
// drmp3 new; // if (!drmp3_init_file(&new, mp3, NULL)) {
// if (!drmp3_init_file(&new, mp3, NULL)) { // YughError("Could not open mp3 file %s.", mp3);
// YughError("Could not open mp3 file %s.", mp3); // }
// }
struct mp3 newmp3 = {}; struct mp3 newmp3 = {};
return newmp3; return newmp3;
} }
void close_audio_device(int device) void close_audio_device(int device) {
{
} }
int open_device(const char *adriver) int open_device(const char *adriver) {
{ return 0;
return 0;
} }
void sound_fillbuf(struct sound *s, short *buf, int n) void sound_fillbuf(struct sound *s, short *buf, int n) {
{ float gainmult = pct2mult(s->data->gain);
float gainmult = pct2mult(s->data->gain);
short *in = s->data->data; short *in = s->data->data;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
for (int j = 0; j < CHANNELS; j++) buf[i*CHANNELS+j] = in[s->frame+j] * gainmult; for (int j = 0; j < CHANNELS; j++)
s->frame++; buf[i * CHANNELS + j] = in[s->frame + j] * gainmult;
if (s->frame == s->data->frames) { s->frame++;
if (s->frame == s->data->frames) {
bus_free(s->bus); bus_free(s->bus);
s->bus = NULL; s->bus = NULL;
s->endcb(s); s->endcb(s);
return; return;
}
} }
}
} }
void mp3_fillbuf(struct sound *s, short *buf, int n) void mp3_fillbuf(struct sound *s, short *buf, int n) {
{
} }
void soundstream_fillbuf(struct soundstream *s, short *buf, int n) void soundstream_fillbuf(struct soundstream *s, short *buf, int n) {
{ int max = s->buf->write - s->buf->read;
int max = s->buf->write - s->buf->read; int lim = (max < n * CHANNELS) ? max : n * CHANNELS;
int lim = (max < n*CHANNELS) ? max : n*CHANNELS; for (int i = 0; i < lim; i++) {
for (int i = 0; i < lim; i++) { buf[i] = cbuf_shift(s->buf);
buf[i] = cbuf_shift(s->buf); }
}
} }
float short2db(short val) float short2db(short val) {
{ return 20 * log10(abs(val) / SHRT_MAX);
return 20*log10(abs(val) / SHRT_MAX);
} }
short db2short(float db) short db2short(float db) {
{ return pow(10, db / 20.f) * SHRT_MAX;
return pow(10, db/20.f) * SHRT_MAX;
} }
short short_gain(short val, float db) short short_gain(short val, float db) {
{ return (short)(pow(10, db / 20.f) * val);
return (short)(pow(10, db/20.f) * val);
} }
float pct2db(float pct) float pct2db(float pct) {
{ if (pct <= 0) return -72.f;
if (pct <= 0) return -72.f;
return 10*log2(pct); return 10 * log2(pct);
} }
float pct2mult(float pct) float pct2mult(float pct) {
{ if (pct <= 0) return 0.f;
if (pct <= 0) return 0.f;
return pow(10, 0.5*log2(pct)); return pow(10, 0.5 * log2(pct));
} }

View file

@ -1,263 +1,240 @@
#include "sprite.h" #include "sprite.h"
#include "timer.h"
#include "render.h"
#include "openglrender.h"
#include "texture.h"
#include "shader.h"
#include "datastream.h" #include "datastream.h"
#include "gameobject.h"
#include <string.h>
#include "stb_ds.h"
#include "log.h"
#include "font.h" #include "font.h"
#include "gameobject.h"
#include "log.h"
#include "openglrender.h"
#include "render.h"
#include "shader.h"
#include "stb_ds.h"
#include "texture.h"
#include "timer.h"
#include <string.h>
struct TextureOptions TEX_SPRITE = { 1, 0, 0 }; struct TextureOptions TEX_SPRITE = {1, 0, 0};
static struct sprite *sprites; static struct sprite *sprites;
static int first = -1; static int first = -1;
sg_pipeline pip_sprite; static sg_pipeline pip_sprite;
sg_bindings bind_sprite; static sg_bindings bind_sprite;
static int sprite_c = 0;
int make_sprite(int go) int make_sprite(int go) {
{ struct sprite sprite = {
struct sprite sprite = { .color = {1.f, 1.f, 1.f},
.color = {1.f, 1.f, 1.f}, .size = {1.f, 1.f},
.size = {1.f, 1.f}, .tex = texture_loadfromfile(NULL),
.tex = texture_loadfromfile(NULL), .go = go,
.go = go, .next = -1,
.next = -1, .layer = 0,
.layer = 0, .enabled = 1};
.enabled = 1 };
if (first<0) { if (first < 0) {
arrput(sprites, sprite); arrput(sprites, sprite);
arrlast(sprites).id = arrlen(sprites)-1; arrlast(sprites).id = arrlen(sprites) - 1;
return arrlen(sprites)-1; return arrlen(sprites) - 1;
} else { } else {
int slot = first; int slot = first;
first = id2sprite(first)->next; first = id2sprite(first)->next;
*id2sprite(slot) = sprite; *id2sprite(slot) = sprite;
return slot; return slot;
} }
} }
void sprite_delete(int id) void sprite_delete(int id) {
{ struct sprite *sp = id2sprite(id);
struct sprite *sp = id2sprite(id); sp->go = -1;
sp->go = -1; sp->next = first;
sp->next = first; first = id;
first = id;
} }
void sprite_enabled(int id, int e) void sprite_enabled(int id, int e) {
{ sprites[id].enabled = e;
sprites[id].enabled = e;
} }
struct sprite *id2sprite(int id) { struct sprite *id2sprite(int id) {
if (id < 0) return NULL; if (id < 0) return NULL;
return &sprites[id]; return &sprites[id];
} }
static sprite_count = 0; static sprite_count = 0;
void sprite_flush() void sprite_flush() {
{
sprite_count = 0; sprite_count = 0;
} }
void sprite_io(struct sprite *sprite, FILE *f, int read) void sprite_io(struct sprite *sprite, FILE *f, int read) {
{ char path[100];
char path[100]; if (read) {
if (read) { // fscanf(f, "%s", &path);
//fscanf(f, "%s", &path); for (int i = 0; i < 100; i++) {
for (int i = 0; i < 100; i++) { path[i] = fgetc(f);
path[i] = fgetc(f);
if (path[i] == '\0') break; if (path[i] == '\0') break;
}
fread(sprite, sizeof(*sprite), 1, f);
sprite_loadtex(sprite, path, ST_UNIT);
} else {
fputs(tex_get_path(sprite->tex), f);
fputc('\0', f);
fwrite(sprite, sizeof(*sprite), 1, f);
} }
fread(sprite, sizeof(*sprite), 1, f);
sprite_loadtex(sprite, path, ST_UNIT);
} else {
fputs(tex_get_path(sprite->tex), f);
fputc('\0', f);
fwrite(sprite, sizeof(*sprite), 1, f);
}
} }
void sprite_draw_all() void sprite_draw_all() {
{ sg_apply_pipeline(pip_sprite);
sg_apply_pipeline(pip_sprite);
static struct sprite **layers[5];
for (int i = 0; i < 5; i++)
arrfree(layers[i]);
for (int i = 0; i < arrlen(sprites); i++) {
if (sprites[i].go >= 0 && sprites[i].enabled) arrpush(layers[sprites[i].layer], &sprites[i]);
}
for (int i = 4; i >= 0; i--) static struct sprite **layers[5];
for (int j = 0; j < arrlen(layers[i]); j++)
sprite_draw(layers[i][j]); for (int i = 0; i < 5; i++)
arrfree(layers[i]);
for (int i = 0; i < arrlen(sprites); i++) {
if (sprites[i].go >= 0 && sprites[i].enabled) arrpush(layers[sprites[i].layer], &sprites[i]);
}
for (int i = 4; i >= 0; i--)
for (int j = 0; j < arrlen(layers[i]); j++)
sprite_draw(layers[i][j]);
} }
void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect frame) void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect frame) {
{ sprite->tex = texture_loadfromfile(path);
sprite->tex = texture_loadfromfile(path); sprite_setframe(sprite, &frame);
sprite_setframe(sprite, &frame);
} }
void sprite_settex(struct sprite *sprite, struct Texture *tex) void sprite_settex(struct sprite *sprite, struct Texture *tex) {
{ sprite->tex = tex;
sprite->tex = tex; sprite_setframe(sprite, &ST_UNIT);
sprite_setframe(sprite, &ST_UNIT);
} }
sg_shader shader_sprite; sg_shader shader_sprite;
void sprite_initialize() void sprite_initialize() {
{ shader_sprite = sg_make_shader(&(sg_shader_desc){
shader_sprite = sg_make_shader(&(sg_shader_desc){
.vs.source = slurp_text("shaders/spritevert.glsl"), .vs.source = slurp_text("shaders/spritevert.glsl"),
.fs.source = slurp_text("shaders/spritefrag.glsl"), .fs.source = slurp_text("shaders/spritefrag.glsl"),
.vs.uniform_blocks[0] = { .vs.uniform_blocks[0] = {
.size = 64, .size = 64,
.layout = SG_UNIFORMLAYOUT_STD140, .layout = SG_UNIFORMLAYOUT_STD140,
.uniforms = { [0] = { .name = "mpv", .type = SG_UNIFORMTYPE_MAT4 }} .uniforms = {[0] = {.name = "mpv", .type = SG_UNIFORMTYPE_MAT4}}},
},
.fs.images[0] = { .fs.images[0] = {
.name = "image", .name = "image",
.image_type = SG_IMAGETYPE_2D, .image_type = SG_IMAGETYPE_2D,
.sampler_type = SG_SAMPLERTYPE_FLOAT, .sampler_type = SG_SAMPLERTYPE_FLOAT,
}, },
.fs.uniform_blocks[0] = { .fs.uniform_blocks[0] = {.size = 12, .uniforms = {[0] = {.name = "spriteColor", .type = SG_UNIFORMTYPE_FLOAT3}}}});
.size = 12,
.uniforms = { [0] = { .name = "spriteColor", .type = SG_UNIFORMTYPE_FLOAT3 }}
}
});
pip_sprite = sg_make_pipeline(&(sg_pipeline_desc){ pip_sprite = sg_make_pipeline(&(sg_pipeline_desc){
.shader = shader_sprite, .shader = shader_sprite,
.layout = { .layout = {
.attrs = { .attrs = {
[0].format=SG_VERTEXFORMAT_FLOAT4 [0].format = SG_VERTEXFORMAT_FLOAT4}},
}
},
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP, .primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
.label = "sprite pipeline" .label = "sprite pipeline"});
});
bind_sprite.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ bind_sprite.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(float)*16*500, .size = sizeof(float) * 16 * 500,
.type = SG_BUFFERTYPE_VERTEXBUFFER, .type = SG_BUFFERTYPE_VERTEXBUFFER,
.usage = SG_USAGE_STREAM, .usage = SG_USAGE_STREAM,
.label = "sprite vertex buffer", .label = "sprite vertex buffer",
}); });
} }
void tex_draw(struct Texture *tex, float pos[2], float angle, float size[2], float offset[2], struct glrect r, float color[3]) { void tex_draw(struct Texture *tex, float pos[2], float angle, float size[2], float offset[2], struct glrect r, float color[3]) {
float model[16] = { 0.f }; float model[16] = {0.f};
mfloat_t r_model[16] = { 0.f }; mfloat_t r_model[16] = {0.f};
memcpy(model, UNITMAT4, sizeof(UNITMAT4)); memcpy(model, UNITMAT4, sizeof(UNITMAT4));
memcpy(r_model, UNITMAT4, sizeof(UNITMAT4)); memcpy(r_model, UNITMAT4, sizeof(UNITMAT4));
mfloat_t t_scale[2] = { tex->width * st_s_w(r) * size[0], tex->height * st_s_h(r) * size[1] }; mfloat_t t_scale[2] = {tex->width * st_s_w(r) * size[0], tex->height * st_s_h(r) * size[1]};
mfloat_t t_offset[2] = { offset[0] * t_scale[0] * size[0], offset[1] * t_scale[1] * size[1]}; mfloat_t t_offset[2] = {offset[0] * t_scale[0] * size[0], offset[1] * t_scale[1] * size[1]};
mat4_translate_vec2(model, t_offset); mat4_translate_vec2(model, t_offset);
mat4_scale_vec2(model, t_scale); mat4_scale_vec2(model, t_scale);
mat4_rotation_z(r_model, angle); mat4_rotation_z(r_model, angle);
mat4_multiply(model, r_model, model); mat4_multiply(model, r_model, model);
mat4_translate_vec2(model, pos); mat4_translate_vec2(model, pos);
mat4_multiply(model, projection,model); mat4_multiply(model, projection, model);
float vertices[] = {
0.f, 0.f, r.s0, r.t1,
1, 0.f, r.s1, r.t1,
0.f, 1, r.s0, r.t0,
1.f, 1.f, r.s1, r.t0
};
bind_sprite.fs_images[0] = tex->id; float vertices[] = {
sg_append_buffer(bind_sprite.vertex_buffers[0], SG_RANGE_REF(vertices)); 0.f, 0.f, r.s0, r.t1,
1, 0.f, r.s1, r.t1,
0.f, 1, r.s0, r.t0,
1.f, 1.f, r.s1, r.t0};
sg_apply_bindings(&bind_sprite); bind_sprite.fs_images[0] = tex->id;
sg_append_buffer(bind_sprite.vertex_buffers[0], SG_RANGE_REF(vertices));
sg_apply_bindings(&bind_sprite);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(model));
sg_range c = {
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(model)); .ptr = color,
float c[3]; .size = sizeof(float) * 3};
for (int i = 0; i < 3; i++) c[i] = color[i]; sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, &c);
sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, SG_RANGE_REF(c));
sg_draw(sprite_count*4,4,1); sg_draw(sprite_count * 4, 4, 1);
sprite_count++; sprite_count++;
} }
void sprite_draw(struct sprite *sprite) void sprite_draw(struct sprite *sprite) {
{ struct gameobject *go = id2go(sprite->go);
struct gameobject *go = id2go(sprite->go);
if (sprite->tex) { if (sprite->tex) {
cpVect cpos = cpBodyGetPosition(go->body); cpVect cpos = cpBodyGetPosition(go->body);
float pos[2] = {cpos.x, cpos.y}; float pos[2] = {cpos.x, cpos.y};
float size[2] = { sprite->size[0] * go->scale * go->flipx, sprite->size[1] * go->scale * go->flipy }; float size[2] = {sprite->size[0] * go->scale * go->flipx, sprite->size[1] * go->scale * go->flipy};
tex_draw(sprite->tex, pos, cpBodyGetAngle(go->body), size, sprite->pos, sprite->frame, sprite->color); tex_draw(sprite->tex, pos, cpBodyGetAngle(go->body), size, sprite->pos, sprite->frame, sprite->color);
} }
} }
void sprite_setanim(struct sprite *sprite, struct TexAnim *anim, int frame) void sprite_setanim(struct sprite *sprite, struct TexAnim *anim, int frame) {
{ if (!sprite) return;
if (!sprite) return; sprite->tex = anim->tex;
sprite->tex = anim->tex; sprite->frame = anim->st_frames[frame];
sprite->frame = anim->st_frames[frame];
} }
void gui_draw_img(const char *img, float x, float y) { void gui_draw_img(const char *img, float x, float y) {
sg_apply_pipeline(pip_sprite); sg_apply_pipeline(pip_sprite);
struct Texture *tex = texture_loadfromfile(img); struct Texture *tex = texture_loadfromfile(img);
float pos[2] = {x, y}; float pos[2] = {x, y};
float size[2] = {1.f, 1.f}; float size[2] = {1.f, 1.f};
float offset[2] = { 0.f, 0.f }; float offset[2] = {0.f, 0.f};
float white[3] = {0.3f,1.f,1.f}; float white[3] = {1.f, 1.f, 1.f};
tex_draw(tex, pos, 0.f, size, offset, tex_get_rect(tex), white); tex_draw(tex, pos, 0.f, size, offset, tex_get_rect(tex), white);
} }
void sprite_setframe(struct sprite *sprite, struct glrect *frame) void sprite_setframe(struct sprite *sprite, struct glrect *frame) {
{ sprite->frame = *frame;
sprite->frame = *frame;
} }
void video_draw(struct datastream *stream, mfloat_t position[2], mfloat_t size[2], float rotate, mfloat_t color[3]) void video_draw(struct datastream *stream, mfloat_t position[2], mfloat_t size[2], float rotate, mfloat_t color[3]) {
{ shader_use(vid_shader);
shader_use(vid_shader);
static mfloat_t model[16]; static mfloat_t model[16];
memcpy(model, UNITMAT4, sizeof(UNITMAT4)); memcpy(model, UNITMAT4, sizeof(UNITMAT4));
mat4_translate_vec2(model, position); mat4_translate_vec2(model, position);
mat4_scale_vec2(model, size); mat4_scale_vec2(model, size);
shader_setmat4(vid_shader, "model", model); shader_setmat4(vid_shader, "model", model);
shader_setvec3(vid_shader, "spriteColor", color); shader_setvec3(vid_shader, "spriteColor", color);
/* /*
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, stream->texture_y); glBindTexture(GL_TEXTURE_2D, stream->texture_y);
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, stream->texture_cb); glBindTexture(GL_TEXTURE_2D, stream->texture_cb);
glActiveTexture(GL_TEXTURE2); glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, stream->texture_cr); glBindTexture(GL_TEXTURE_2D, stream->texture_cr);
// TODO: video bind VAO // TODO: video bind VAO
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
*/ */
} }

View file

@ -1,208 +1,184 @@
#include "texture.h" #include "texture.h"
#include "render.h"
#include <stdio.h>
#include <stb_image.h>
#include <stb_ds.h>
#include "log.h" #include "log.h"
#include <math.h> #include "render.h"
#include "util.h"
#include "sokol/sokol_gfx.h" #include "sokol/sokol_gfx.h"
#include "util.h"
#include <math.h>
#include <stb_ds.h>
#include <stb_image.h>
#include <stdio.h>
struct glrect ST_UNIT = { 0.f, 1.f, 0.f, 1.f }; struct glrect ST_UNIT = {0.f, 1.f, 0.f, 1.f};
static struct { static struct {
char *key; char *key;
struct Texture *value; struct Texture *value;
} *texhash = NULL; } *texhash = NULL;
struct Texture *tex_default; struct Texture *tex_default;
struct Texture *texture_notex() struct Texture *texture_notex() {
{
return texture_pullfromfile("./icons/no_tex.png"); return texture_pullfromfile("./icons/no_tex.png");
} }
/* If an empty string or null is put for path, loads default texture */ /* If an empty string or null is put for path, loads default texture */
struct Texture *texture_pullfromfile(const char *path) struct Texture *texture_pullfromfile(const char *path) {
{ if (!path) return texture_notex();
if (!path) return texture_notex();
int index = shgeti(texhash, path);
if (index != -1)
return texhash[index].value;
YughInfo("Loading texture %s.", path); int index = shgeti(texhash, path);
struct Texture *tex = calloc(1, sizeof(*tex)); if (index != -1)
tex->opts.sprite = 1; return texhash[index].value;
tex->opts.mips = 0;
tex->opts.gamma = 0;
int n;
unsigned char *data = stbi_load(path, &tex->width, &tex->height, &n, 4);
if (data == NULL) { YughInfo("Loading texture %s.", path);
YughError("STBI failed to load file %s with message: %s\nOpening default instead.", path, stbi_failure_reason()); struct Texture *tex = calloc(1, sizeof(*tex));
return texture_notex(); tex->opts.sprite = 1;
} tex->opts.mips = 0;
tex->data = data; tex->opts.gamma = 0;
int filter; int n;
if (tex->opts.sprite) { unsigned char *data = stbi_load(path, &tex->width, &tex->height, &n, 4);
if (tex->opts.mips)
filter = SG_FILTER_NEAREST_MIPMAP_NEAREST;
else
filter = SG_FILTER_NEAREST;
} else {
if (tex->opts.mips)
filter = SG_FILTER_LINEAR_MIPMAP_LINEAR;
else
filter = SG_FILTER_LINEAR;
}
tex->id = sg_make_image(&(sg_image_desc){ if (data == NULL) {
YughError("STBI failed to load file %s with message: %s\nOpening default instead.", path, stbi_failure_reason());
return texture_notex();
}
tex->data = data;
int filter;
if (tex->opts.sprite) {
filter = SG_FILTER_NEAREST;
} else {
filter = SG_FILTER_LINEAR;
}
tex->id = sg_make_image(&(sg_image_desc){
.type = SG_IMAGETYPE_2D, .type = SG_IMAGETYPE_2D,
.width = tex->width, .width = tex->width,
.height = tex->height, .height = tex->height,
.usage = SG_USAGE_IMMUTABLE, .usage = SG_USAGE_IMMUTABLE,
.min_filter = filter, .min_filter = filter,
.mag_filter = filter, .mag_filter = filter,
.max_anisotropy = 16,
.data.subimage[0][0] = { .data.subimage[0][0] = {
.ptr = data, .ptr = data,
.size = tex->width*tex->height*4 .size = tex->width * tex->height * 4}});
}
});
if (shlen(texhash) == 0) if (shlen(texhash) == 0)
sh_new_arena(texhash); sh_new_arena(texhash);
shput(texhash, path, tex); shput(texhash, path, tex);
return tex; return tex;
} }
void texture_sync(const char *path) void texture_sync(const char *path) {
{
YughWarn("Need to implement texture sync."); YughWarn("Need to implement texture sync.");
} }
char *tex_get_path(struct Texture *tex) { char *tex_get_path(struct Texture *tex) {
for (int i = 0; i < shlen(texhash); i++) { for (int i = 0; i < shlen(texhash); i++) {
if (tex == texhash[i].value) { if (tex == texhash[i].value) {
YughInfo("Found key %s", texhash[i].key); YughInfo("Found key %s", texhash[i].key);
return texhash[i].key; return texhash[i].key;
}
} }
}
return NULL; return NULL;
} }
struct Texture *texture_loadfromfile(const char *path) struct Texture *texture_loadfromfile(const char *path) {
{ struct Texture *new = texture_pullfromfile(path);
struct Texture *new = texture_pullfromfile(path); /*
/* if (new->id == 0) {
if (new->id == 0) { glGenTextures(1, &new->id);
glGenTextures(1, &new->id);
//tex_gpu_load(new); //tex_gpu_load(new);
YughInfo("Loaded texture path %s", path); YughInfo("Loaded texture path %s", path);
} }
*/ */
return new; return new;
} }
void tex_gpu_reload(struct Texture *tex) void tex_gpu_reload(struct Texture *tex) {
{ tex_gpu_free(tex);
tex_gpu_free(tex);
//tex_gpu_load(tex); // tex_gpu_load(tex);
} }
void anim_calc(struct anim2d *anim) void anim_calc(struct anim2d *anim) {
{ anim->size[0] = anim->anim->tex->width * st_s_w(anim->anim->st_frames[anim->frame]);
anim->size[0] = anim->anim->tex->width * st_s_w(anim->anim->st_frames[anim->frame]); anim->size[1] = anim->anim->tex->height * st_s_h(anim->anim->st_frames[anim->frame]);
anim->size[1] = anim->anim->tex->height * st_s_h(anim->anim->st_frames[anim->frame]);
} }
void anim_incr(struct anim2d *anim) void anim_incr(struct anim2d *anim) {
{ anim->frame = (anim->frame + 1) % arrlen(anim->anim->st_frames);
anim->frame = (anim->frame + 1) % arrlen(anim->anim->st_frames);
if (!anim->anim->loop && anim->frame == arrlen(anim->anim->st_frames)) if (!anim->anim->loop && anim->frame == arrlen(anim->anim->st_frames))
anim_pause(anim); anim_pause(anim);
anim_calc(anim); anim_calc(anim);
} }
void anim_decr(struct anim2d *anim) void anim_decr(struct anim2d *anim) {
{ anim->frame = (anim->frame + arrlen(anim->anim->st_frames) - 1) % arrlen(anim->anim->st_frames);
anim->frame = (anim->frame + arrlen(anim->anim->st_frames) - 1) % arrlen(anim->anim->st_frames); anim_calc(anim);
anim_calc(anim);
} }
struct glrect anim_get_rect(struct anim2d *anim) struct glrect anim_get_rect(struct anim2d *anim) {
{ return anim->anim->st_frames[anim->frame];
return anim->anim->st_frames[anim->frame];
} }
void anim_setframe(struct anim2d *anim, int frame) void anim_setframe(struct anim2d *anim, int frame) {
{ anim->frame = frame;
anim->frame = frame; anim_calc(anim);
anim_calc(anim);
} }
struct TexAnim *anim2d_from_tex(const char *path, int frames, int fps) struct TexAnim *anim2d_from_tex(const char *path, int frames, int fps) {
{ struct TexAnim *anim = malloc(sizeof(*anim));
struct TexAnim *anim = malloc(sizeof(*anim)); anim->tex = texture_loadfromfile(path);
anim->tex = texture_loadfromfile(path); texanim_fromframes(anim, frames);
texanim_fromframes(anim, frames); anim->ms = (float)1 / fps;
anim->ms = (float)1/fps;
return anim; return anim;
} }
void texanim_fromframes(struct TexAnim *anim, int frames) void texanim_fromframes(struct TexAnim *anim, int frames) {
{ if (anim->st_frames) {
if (anim->st_frames) { free(anim->st_frames);
free(anim->st_frames); }
}
arrsetlen(anim->st_frames, frames); arrsetlen(anim->st_frames, frames);
float width = (float)1/frames; float width = (float)1 / frames;
for (int i = 0; i < frames; i++) { for (int i = 0; i < frames; i++) {
anim->st_frames[i].s0 = width*i; anim->st_frames[i].s0 = width * i;
anim->st_frames[i].s1 = width*(i+1); anim->st_frames[i].s1 = width * (i + 1);
anim->st_frames[i].t0 = 0.f; anim->st_frames[i].t0 = 0.f;
anim->st_frames[i].t1 = 1.f; anim->st_frames[i].t1 = 1.f;
} }
} }
void tex_gpu_free(struct Texture *tex) void tex_gpu_free(struct Texture *tex) {
{ /*
/* if (tex->id != 0) {
if (tex->id != 0) { glDeleteTextures(1, &tex->id);
glDeleteTextures(1, &tex->id); tex->id = 0;
tex->id = 0; }
} */
*/
} }
int anim_frames(struct TexAnim *a) int anim_frames(struct TexAnim *a) {
{ return arrlen(a->st_frames);
return arrlen(a->st_frames);
} }
struct glrect tex_get_rect(struct Texture *tex) struct glrect tex_get_rect(struct Texture *tex) {
{ return ST_UNIT;
return ST_UNIT;
} }
cpVect tex_get_dimensions(struct Texture *tex) cpVect tex_get_dimensions(struct Texture *tex) {
{
if (!tex) return cpvzero; if (!tex) return cpvzero;
cpVect d; cpVect d;
d.x = tex->width; d.x = tex->width;
@ -210,78 +186,69 @@ cpVect tex_get_dimensions(struct Texture *tex)
return d; return d;
} }
void tex_bind(struct Texture *tex) void tex_bind(struct Texture *tex) {
{ /* glActiveTexture(GL_TEXTURE0);
/* glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex->id);
glBindTexture(GL_TEXTURE_2D, tex->id); glBindTexture(GL_TEXTURE_2D_ARRAY, tex->id);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex->id); */
*/
} }
/********************** ANIM2D ****************/ /********************** ANIM2D ****************/
void anim_load(struct anim2d *anim, const char *path) void anim_load(struct anim2d *anim, const char *path) {
{ anim->anim = &texture_pullfromfile(path)->anim;
anim->anim = &texture_pullfromfile(path)->anim; anim->anim->tex->opts.animation = 1;
anim->anim->tex->opts.animation = 1; anim_stop(anim);
anim_stop(anim); anim_play(anim);
anim_play(anim);
} }
void anim_play(struct anim2d *anim) void anim_play(struct anim2d *anim) {
{ if (anim->playing)
if (anim->playing) return;
return;
if (anim->frame == anim_frames(anim->anim)) if (anim->frame == anim_frames(anim->anim))
anim->frame = 0;
anim->playing = 1;
if (anim->timer == NULL)
anim->timer = id2timer(timer_make(1.f / anim->anim->ms, anim_incr, anim, 0));
else
timerr_settime(anim->timer, 1.f/anim->anim->ms);
timer_start(anim->timer);
}
void anim_stop(struct anim2d *anim)
{
if (!anim->playing)
return;
anim->playing = 0;
anim->frame = 0; anim->frame = 0;
anim->pausetime = 0;
timer_stop(anim->timer); anim->playing = 1;
if (anim->timer == NULL)
anim->timer = id2timer(timer_make(1.f / anim->anim->ms, anim_incr, anim, 0));
else
timerr_settime(anim->timer, 1.f / anim->anim->ms);
timer_start(anim->timer);
} }
void anim_pause(struct anim2d *anim) void anim_stop(struct anim2d *anim) {
{ if (!anim->playing)
if (!anim->playing) return;
return;
anim->playing = 0; anim->playing = 0;
timer_pause(anim->timer); anim->frame = 0;
anim->pausetime = 0;
timer_stop(anim->timer);
} }
void anim_fwd(struct anim2d *anim) void anim_pause(struct anim2d *anim) {
{ if (!anim->playing)
anim_incr(anim); return;
anim->playing = 0;
timer_pause(anim->timer);
} }
void anim_bkwd(struct anim2d *anim) void anim_fwd(struct anim2d *anim) {
{ anim_incr(anim);
anim_decr(anim);
} }
float st_s_w(struct glrect st) void anim_bkwd(struct anim2d *anim) {
{ anim_decr(anim);
return (st.s1 - st.s0);
} }
float st_s_h(struct glrect st) float st_s_w(struct glrect st) {
{ return (st.s1 - st.s0);
return (st.t1 - st.t0); }
float st_s_h(struct glrect st) {
return (st.t1 - st.t0);
} }

View file

@ -372,7 +372,7 @@ extern "C" {
#elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
#define NK_SIZE_TYPE unsigned __int32 #define NK_SIZE_TYPE unsigned __int32
#elif defined(__GNUC__) || defined(__clang__) #elif defined(__GNUC__) || defined(__clang__)
#if defined(__x86_64__) || defined(__ppc64__) #if defined(__x86_64__) || defined(__ppc64__) || defined(__aarch64__)
#define NK_SIZE_TYPE unsigned long #define NK_SIZE_TYPE unsigned long
#else #else
#define NK_SIZE_TYPE unsigned int #define NK_SIZE_TYPE unsigned int
@ -387,7 +387,7 @@ extern "C" {
#elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
#define NK_POINTER_TYPE unsigned __int32 #define NK_POINTER_TYPE unsigned __int32
#elif defined(__GNUC__) || defined(__clang__) #elif defined(__GNUC__) || defined(__clang__)
#if defined(__x86_64__) || defined(__ppc64__) #if defined(__x86_64__) || defined(__ppc64__) || defined(__aarch64__)
#define NK_POINTER_TYPE unsigned long #define NK_POINTER_TYPE unsigned long
#else #else
#define NK_POINTER_TYPE unsigned int #define NK_POINTER_TYPE unsigned int
@ -432,8 +432,8 @@ NK_STATIC_ASSERT(sizeof(nk_int) == 4);
NK_STATIC_ASSERT(sizeof(nk_byte) == 1); NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
//NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
//NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*)); NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
#ifdef NK_INCLUDE_STANDARD_BOOL #ifdef NK_INCLUDE_STANDARD_BOOL
NK_STATIC_ASSERT(sizeof(nk_bool) == sizeof(bool)); NK_STATIC_ASSERT(sizeof(nk_bool) == sizeof(bool));
#else #else
@ -1127,7 +1127,7 @@ NK_API void nk_input_end(struct nk_context*);
/// cfg.curve_segment_count = 22; /// cfg.curve_segment_count = 22;
/// cfg.arc_segment_count = 22; /// cfg.arc_segment_count = 22;
/// cfg.global_alpha = 1.0f; /// cfg.global_alpha = 1.0f;
/// cfg.null = dev->null; /// cfg.tex_null = dev->tex_null;
/// // /// //
/// // setup buffers and convert /// // setup buffers and convert
/// struct nk_buffer cmds, verts, idx; /// struct nk_buffer cmds, verts, idx;
@ -1177,7 +1177,7 @@ struct nk_convert_config {
unsigned circle_segment_count; /* number of segments used for circles: default to 22 */ unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */ unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
unsigned curve_segment_count; /* number of segments used for curves: default to 22 */ unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */ struct nk_draw_null_texture tex_null; /* handle to texture with a white pixel for shape drawing */
const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */ const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
nk_size vertex_size; /* sizeof one vertex for vertex packing */ nk_size vertex_size; /* sizeof one vertex for vertex packing */
nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */ nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
@ -6078,7 +6078,6 @@ NK_LIB void nk_property(struct nk_context *ctx, const char *name, struct nk_prop
#define STB_RECT_PACK_IMPLEMENTATION #define STB_RECT_PACK_IMPLEMENTATION
#define STB_TRUETYPE_IMPLEMENTATION #define STB_TRUETYPE_IMPLEMENTATION
#define STBTT_STATIC
/* Allow consumer to define own STBTT_malloc/STBTT_free, and use the font atlas' allocator otherwise */ /* Allow consumer to define own STBTT_malloc/STBTT_free, and use the font atlas' allocator otherwise */
#ifndef STBTT_malloc #ifndef STBTT_malloc
@ -8440,7 +8439,6 @@ nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
NK_API int NK_API int
nk_str_append_str_utf8(struct nk_str *str, const char *text) nk_str_append_str_utf8(struct nk_str *str, const char *text)
{ {
int runes = 0;
int byte_len = 0; int byte_len = 0;
int num_runes = 0; int num_runes = 0;
int glyph_len = 0; int glyph_len = 0;
@ -8454,7 +8452,7 @@ nk_str_append_str_utf8(struct nk_str *str, const char *text)
num_runes++; num_runes++;
} }
nk_str_append_text_char(str, text, byte_len); nk_str_append_text_char(str, text, byte_len);
return runes; return num_runes;
} }
NK_API int NK_API int
nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len) nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
@ -8569,7 +8567,6 @@ nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
NK_API int NK_API int
nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text) nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
{ {
int runes = 0;
int byte_len = 0; int byte_len = 0;
int num_runes = 0; int num_runes = 0;
int glyph_len = 0; int glyph_len = 0;
@ -8583,7 +8580,7 @@ nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
num_runes++; num_runes++;
} }
nk_str_insert_at_rune(str, pos, text, byte_len); nk_str_insert_at_rune(str, pos, text, byte_len);
return runes; return num_runes;
} }
NK_API int NK_API int
nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len) nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
@ -9564,7 +9561,7 @@ nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
NK_ASSERT(list); NK_ASSERT(list);
if (!list) return; if (!list) return;
if (!list->cmd_count) { if (!list->cmd_count) {
nk_draw_list_push_command(list, rect, list->config.null.texture); nk_draw_list_push_command(list, rect, list->config.tex_null.texture);
} else { } else {
struct nk_draw_command *prev = nk_draw_list_command_last(list); struct nk_draw_command *prev = nk_draw_list_command_last(list);
if (prev->elem_count == 0) if (prev->elem_count == 0)
@ -9919,7 +9916,7 @@ nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *p
/* fill vertices */ /* fill vertices */
for (i = 0; i < points_count; ++i) { for (i = 0; i < points_count; ++i) {
const struct nk_vec2 uv = list->config.null.uv; const struct nk_vec2 uv = list->config.tex_null.uv;
vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col); vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans); vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans); vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
@ -9984,7 +9981,7 @@ nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *p
/* add vertices */ /* add vertices */
for (i = 0; i < points_count; ++i) { for (i = 0; i < points_count; ++i) {
const struct nk_vec2 uv = list->config.null.uv; const struct nk_vec2 uv = list->config.tex_null.uv;
vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans); vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col); vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col); vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
@ -10005,7 +10002,7 @@ nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *p
for (i1 = 0; i1 < count; ++i1) { for (i1 = 0; i1 < count; ++i1) {
float dx, dy; float dx, dy;
const struct nk_vec2 uv = list->config.null.uv; const struct nk_vec2 uv = list->config.tex_null.uv;
const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1; const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
const struct nk_vec2 p1 = points[i1]; const struct nk_vec2 p1 = points[i1];
const struct nk_vec2 p2 = points[i2]; const struct nk_vec2 p2 = points[i2];
@ -10115,7 +10112,7 @@ nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
/* add vertices + indexes */ /* add vertices + indexes */
for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
const struct nk_vec2 uv = list->config.null.uv; const struct nk_vec2 uv = list->config.tex_null.uv;
struct nk_vec2 n0 = normals[i0]; struct nk_vec2 n0 = normals[i0];
struct nk_vec2 n1 = normals[i1]; struct nk_vec2 n1 = normals[i1];
struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f); struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
@ -10152,7 +10149,7 @@ nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
if (!vtx || !ids) return; if (!vtx || !ids) return;
for (i = 0; i < vtx_count; ++i) for (i = 0; i < vtx_count; ++i)
vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col); vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.tex_null.uv, col);
for (i = 2; i < points_count; ++i) { for (i = 2; i < points_count; ++i) {
ids[0] = (nk_draw_index)index; ids[0] = (nk_draw_index)index;
ids[1] = (nk_draw_index)(index+ i - 1); ids[1] = (nk_draw_index)(index+ i - 1);
@ -10181,8 +10178,8 @@ nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
nk_draw_list_add_clip(list, nk_null_rect); nk_draw_list_add_clip(list, nk_null_rect);
cmd = nk_draw_list_command_last(list); cmd = nk_draw_list_command_last(list);
if (cmd && cmd->texture.ptr != list->config.null.texture.ptr) if (cmd && cmd->texture.ptr != list->config.tex_null.texture.ptr)
nk_draw_list_push_image(list, list->config.null.texture); nk_draw_list_push_image(list, list->config.tex_null.texture);
points = nk_draw_list_alloc_path(list, 1); points = nk_draw_list_alloc_path(list, 1);
if (!points) return; if (!points) return;
@ -10384,7 +10381,7 @@ nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rec
NK_ASSERT(list); NK_ASSERT(list);
if (!list) return; if (!list) return;
nk_draw_list_push_image(list, list->config.null.texture); nk_draw_list_push_image(list, list->config.tex_null.texture);
index = (nk_draw_index)list->vertex_count; index = (nk_draw_index)list->vertex_count;
vtx = nk_draw_list_alloc_vertices(list, 4); vtx = nk_draw_list_alloc_vertices(list, 4);
idx = nk_draw_list_alloc_elements(list, 6); idx = nk_draw_list_alloc_elements(list, 6);
@ -10394,10 +10391,10 @@ nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rec
idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left); vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.tex_null.uv, col_left);
vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top); vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.tex_null.uv, col_top);
vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right); vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.tex_null.uv, col_right);
vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom); vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.tex_null.uv, col_bottom);
} }
NK_API void NK_API void
nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a, nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
@ -16513,7 +16510,7 @@ nk_font_chinese_glyph_ranges(void)
0x3000, 0x30FF, 0x3000, 0x30FF,
0x31F0, 0x31FF, 0x31F0, 0x31FF,
0xFF00, 0xFFEF, 0xFF00, 0xFFEF,
0x4e00, 0x9FAF, 0x4E00, 0x9FAF,
0 0
}; };
return ranges; return ranges;
@ -16622,7 +16619,7 @@ nk_font_bake_pack(struct nk_font_baker *baker,
struct stbtt_fontinfo *font_info = &baker->build[i++].info; struct stbtt_fontinfo *font_info = &baker->build[i++].info;
font_info->userdata = alloc; font_info->userdata = alloc;
if (!stbtt_InitFont(font_info, (const unsigned char*)it->ttf_blob, 0)) if (!stbtt_InitFont(font_info, (const unsigned char*)it->ttf_blob, stbtt_GetFontOffsetForIndex((const unsigned char*)it->ttf_blob, 0)))
return nk_false; return nk_false;
} while ((it = it->n) != config_iter); } while ((it = it->n) != config_iter);
} }
@ -17704,20 +17701,20 @@ failed:
} }
NK_API void NK_API void
nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture, nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
struct nk_draw_null_texture *null) struct nk_draw_null_texture *tex_null)
{ {
int i = 0; int i = 0;
struct nk_font *font_iter; struct nk_font *font_iter;
NK_ASSERT(atlas); NK_ASSERT(atlas);
if (!atlas) { if (!atlas) {
if (!null) return; if (!tex_null) return;
null->texture = texture; tex_null->texture = texture;
null->uv = nk_vec2(0.5f,0.5f); tex_null->uv = nk_vec2(0.5f,0.5f);
} }
if (null) { if (tex_null) {
null->texture = texture; tex_null->texture = texture;
null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width; tex_null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height; tex_null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
} }
for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
font_iter->texture = texture; font_iter->texture = texture;
@ -26163,7 +26160,7 @@ nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
text+text_len, 1)) text+text_len, 1))
{ {
nk_textedit_makeundo_insert(state, state->cursor, 1); nk_textedit_makeundo_insert(state, state->cursor, 1);
++state->cursor; state->cursor = NK_MIN(state->cursor + 1, state->string.len);
state->has_preferred_x = 0; state->has_preferred_x = 0;
} }
} }
@ -29657,6 +29654,12 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
/// - [y]: Minor version with non-breaking API and library changes /// - [y]: Minor version with non-breaking API and library changes
/// - [z]: Patch version with no direct changes to the API /// - [z]: Patch version with no direct changes to the API
/// ///
/// - 2022/12/17 (4.10.5) - Fix nk_font_bake_pack() using TTC font offset incorrectly
/// - 2022/10/24 (4.10.4) - Fix nk_str_{append,insert}_str_utf8 always returning 0
/// - 2022/09/03 (4.10.3) - Renamed the `null` texture variable to `tex_null`
/// - 2022/08/01 (4.10.2) - Fix Apple Silicon with incorrect NK_SITE_TYPE and NK_POINTER_TYPE
/// - 2022/08/01 (4.10.1) - Fix cursor jumping back to beginning of text when typing more than
/// nk_edit_xxx limit
/// - 2022/05/27 (4.10.0) - Add nk_input_has_mouse_click_in_button_rect() to fix window move bug /// - 2022/05/27 (4.10.0) - Add nk_input_has_mouse_click_in_button_rect() to fix window move bug
/// - 2022/04/18 (4.9.7) - Change button behavior when NK_BUTTON_TRIGGER_ON_RELEASE is defined to /// - 2022/04/18 (4.9.7) - Change button behavior when NK_BUTTON_TRIGGER_ON_RELEASE is defined to
/// only trigger when the mouse position was inside the same button on down /// only trigger when the mouse position was inside the same button on down

View file

@ -1,500 +0,0 @@
/*
* Nuklear - 1.32.0 - public domain
* no warrenty implied; use at your own risk.
* authored from 2015-2016 by Micha Mettke
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_GLFW_GL3_H_
#define NK_GLFW_GL3_H_
#include <glad/gl.h>
#include <GLFW/glfw3.h>
enum nk_glfw_init_state{
NK_GLFW3_DEFAULT=0,
NK_GLFW3_INSTALL_CALLBACKS
};
#ifndef NK_GLFW_TEXT_MAX
#define NK_GLFW_TEXT_MAX 256
#endif
struct nk_glfw_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
GLuint vbo, vao, ebo;
GLuint prog;
GLuint vert_shdr;
GLuint frag_shdr;
GLint attrib_pos;
GLint attrib_uv;
GLint attrib_col;
GLint uniform_tex;
GLint uniform_proj;
GLuint font_tex;
};
struct nk_glfw {
GLFWwindow *win;
int width, height;
int display_width, display_height;
struct nk_glfw_device ogl;
struct nk_context ctx;
struct nk_font_atlas atlas;
struct nk_vec2 fb_scale;
unsigned int text[NK_GLFW_TEXT_MAX];
int text_len;
struct nk_vec2 scroll;
double last_button_click;
int is_double_click_down;
struct nk_vec2 double_click_pos;
};
NK_API struct nk_context* nk_glfw3_init(struct nk_glfw* glfw, GLFWwindow *win, enum nk_glfw_init_state);
NK_API void nk_glfw3_shutdown(struct nk_glfw* glfw);
NK_API void nk_glfw3_font_stash_begin(struct nk_glfw* glfw, struct nk_font_atlas **atlas);
NK_API void nk_glfw3_font_stash_end(struct nk_glfw* glfw);
NK_API void nk_glfw3_new_frame(struct nk_glfw* glfw);
NK_API void nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer);
NK_API void nk_glfw3_device_destroy(struct nk_glfw* glfw);
NK_API void nk_glfw3_device_create(struct nk_glfw* glfw);
NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
NK_API void nk_glfw3_mouse_button_callback(GLFWwindow *win, int button, int action, int mods);
#endif
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_GLFW_GL3_IMPLEMENTATION
#ifndef NK_GLFW_DOUBLE_CLICK_LO
#define NK_GLFW_DOUBLE_CLICK_LO 0.02
#endif
#ifndef NK_GLFW_DOUBLE_CLICK_HI
#define NK_GLFW_DOUBLE_CLICK_HI 0.2
#endif
struct nk_glfw_vertex {
float position[2];
float uv[2];
nk_byte col[4];
};
#ifdef __APPLE__
#define NK_SHADER_VERSION "#version 150\n"
#else
#define NK_SHADER_VERSION "#version 300 es\n"
#endif
NK_API void
nk_glfw3_device_create(struct nk_glfw* glfw)
{
GLint status;
static const GLchar *vertex_shader =
NK_SHADER_VERSION
"uniform mat4 ProjMtx;\n"
"in vec2 Position;\n"
"in vec2 TexCoord;\n"
"in vec4 Color;\n"
"out vec2 Frag_UV;\n"
"out vec4 Frag_Color;\n"
"void main() {\n"
" Frag_UV = TexCoord;\n"
" Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n"
"}\n";
static const GLchar *fragment_shader =
NK_SHADER_VERSION
"precision mediump float;\n"
"uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n"
"out vec4 Out_Color;\n"
"void main(){\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n";
struct nk_glfw_device *dev = &glfw->ogl;
nk_buffer_init_default(&dev->cmds);
dev->prog = glCreateProgram();
dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER);
dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0);
glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0);
glCompileShader(dev->vert_shdr);
glCompileShader(dev->frag_shdr);
glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status);
assert(status == GL_TRUE);
glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status);
assert(status == GL_TRUE);
glAttachShader(dev->prog, dev->vert_shdr);
glAttachShader(dev->prog, dev->frag_shdr);
glLinkProgram(dev->prog);
glGetProgramiv(dev->prog, GL_LINK_STATUS, &status);
assert(status == GL_TRUE);
dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture");
dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx");
dev->attrib_pos = glGetAttribLocation(dev->prog, "Position");
dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord");
dev->attrib_col = glGetAttribLocation(dev->prog, "Color");
{
/* buffer setup */
GLsizei vs = sizeof(struct nk_glfw_vertex);
size_t vp = offsetof(struct nk_glfw_vertex, position);
size_t vt = offsetof(struct nk_glfw_vertex, uv);
size_t vc = offsetof(struct nk_glfw_vertex, col);
glGenBuffers(1, &dev->vbo);
glGenBuffers(1, &dev->ebo);
glGenVertexArrays(1, &dev->vao);
glBindVertexArray(dev->vao);
glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
glEnableVertexAttribArray((GLuint)dev->attrib_pos);
glEnableVertexAttribArray((GLuint)dev->attrib_uv);
glEnableVertexAttribArray((GLuint)dev->attrib_col);
glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
}
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
NK_INTERN void
nk_glfw3_device_upload_atlas(struct nk_glfw* glfw, const void *image, int width, int height)
{
struct nk_glfw_device *dev = &glfw->ogl;
glGenTextures(1, &dev->font_tex);
glBindTexture(GL_TEXTURE_2D, dev->font_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image);
}
NK_API void
nk_glfw3_device_destroy(struct nk_glfw* glfw)
{
struct nk_glfw_device *dev = &glfw->ogl;
glDetachShader(dev->prog, dev->vert_shdr);
glDetachShader(dev->prog, dev->frag_shdr);
glDeleteShader(dev->vert_shdr);
glDeleteShader(dev->frag_shdr);
glDeleteProgram(dev->prog);
glDeleteTextures(1, &dev->font_tex);
glDeleteBuffers(1, &dev->vbo);
glDeleteBuffers(1, &dev->ebo);
nk_buffer_free(&dev->cmds);
}
NK_API void
nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer)
{
struct nk_glfw_device *dev = &glfw->ogl;
struct nk_buffer vbuf, ebuf;
GLfloat ortho[4][4] = {
{2.0f, 0.0f, 0.0f, 0.0f},
{0.0f,-2.0f, 0.0f, 0.0f},
{0.0f, 0.0f,-1.0f, 0.0f},
{-1.0f,1.0f, 0.0f, 1.0f},
};
ortho[0][0] /= (GLfloat)glfw->width;
ortho[1][1] /= (GLfloat)glfw->height;
/* setup global state */
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
glActiveTexture(GL_TEXTURE0);
/* setup program */
glUseProgram(dev->prog);
glUniform1i(dev->uniform_tex, 0);
glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
glViewport(0,0,(GLsizei)glfw->display_width,(GLsizei)glfw->display_height);
{
/* convert from command queue into draw list and draw to screen */
const struct nk_draw_command *cmd;
void *vertices, *elements;
const nk_draw_index *offset = NULL;
/* allocate vertex and element buffer */
glBindVertexArray(dev->vao);
glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW);
/* load draw vertices & elements directly into vertex + element buffer */
vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
{
/* fill convert configuration */
struct nk_convert_config config;
static const struct nk_draw_vertex_layout_element vertex_layout[] = {
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
{NK_VERTEX_LAYOUT_END}
};
memset(&config, 0, sizeof(config));
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_glfw_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
config.null = dev->null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
config.global_alpha = 1.0f;
config.shape_AA = AA;
config.line_AA = AA;
/* setup buffers to load vertices and elements */
nk_buffer_init_fixed(&vbuf, vertices, (size_t)max_vertex_buffer);
nk_buffer_init_fixed(&ebuf, elements, (size_t)max_element_buffer);
nk_convert(&glfw->ctx, &dev->cmds, &vbuf, &ebuf, &config);
}
glUnmapBuffer(GL_ARRAY_BUFFER);
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
/* iterate over and execute each draw command */
nk_draw_foreach(cmd, &glfw->ctx, &dev->cmds)
{
if (!cmd->elem_count) continue;
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
glScissor(
(GLint)(cmd->clip_rect.x * glfw->fb_scale.x),
(GLint)((glfw->height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw->fb_scale.y),
(GLint)(cmd->clip_rect.w * glfw->fb_scale.x),
(GLint)(cmd->clip_rect.h * glfw->fb_scale.y));
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
offset += cmd->elem_count;
}
nk_clear(&glfw->ctx);
nk_buffer_clear(&dev->cmds);
}
/* default OpenGL state */
glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
}
NK_API void
nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
{
struct nk_glfw* glfw = glfwGetWindowUserPointer(win);
if (glfw->text_len < NK_GLFW_TEXT_MAX)
glfw->text[glfw->text_len++] = codepoint;
}
NK_API void
nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
{
struct nk_glfw* glfw = glfwGetWindowUserPointer(win);
(void)xoff;
glfw->scroll.x += (float)xoff;
glfw->scroll.y += (float)yoff;
}
NK_API void
nk_glfw3_mouse_button_callback(GLFWwindow* win, int button, int action, int mods)
{
struct nk_glfw* glfw = glfwGetWindowUserPointer(win);
double x, y;
NK_UNUSED(mods);
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
glfwGetCursorPos(win, &x, &y);
if (action == GLFW_PRESS) {
double dt = glfwGetTime() - glfw->last_button_click;
if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI) {
glfw->is_double_click_down = nk_true;
glfw->double_click_pos = nk_vec2((float)x, (float)y);
}
glfw->last_button_click = glfwGetTime();
} else glfw->is_double_click_down = nk_false;
}
NK_INTERN void
nk_glfw3_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{
struct nk_glfw* glfw = (struct nk_glfw*)usr.ptr;
const char *text = glfwGetClipboardString(glfw->win);
if (text) nk_textedit_paste(edit, text, nk_strlen(text));
(void)usr;
}
NK_INTERN void
nk_glfw3_clipboard_copy(nk_handle usr, const char *text, int len)
{
struct nk_glfw* glfw = (struct nk_glfw*)usr.ptr;
char *str = 0;
if (!len) return;
str = (char*)malloc((size_t)len+1);
if (!str) return;
memcpy(str, text, (size_t)len);
str[len] = '\0';
glfwSetClipboardString(glfw->win, str);
free(str);
}
NK_API struct nk_context*
nk_glfw3_init(struct nk_glfw* glfw, GLFWwindow *win, enum nk_glfw_init_state init_state)
{
glfwSetWindowUserPointer(win, glfw);
glfw->win = win;
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
glfwSetCharCallback(win, nk_glfw3_char_callback);
glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
}
nk_init_default(&glfw->ctx, 0);
glfw->ctx.clip.copy = nk_glfw3_clipboard_copy;
glfw->ctx.clip.paste = nk_glfw3_clipboard_paste;
glfw->ctx.clip.userdata = nk_handle_ptr(&glfw);
glfw->last_button_click = 0;
nk_glfw3_device_create(glfw);
glfw->is_double_click_down = nk_false;
glfw->double_click_pos = nk_vec2(0, 0);
return &glfw->ctx;
}
NK_API void
nk_glfw3_font_stash_begin(struct nk_glfw* glfw, struct nk_font_atlas **atlas)
{
nk_font_atlas_init_default(&glfw->atlas);
nk_font_atlas_begin(&glfw->atlas);
*atlas = &glfw->atlas;
}
NK_API void
nk_glfw3_font_stash_end(struct nk_glfw* glfw)
{
const void *image; int w, h;
image = nk_font_atlas_bake(&glfw->atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_glfw3_device_upload_atlas(glfw, image, w, h);
nk_font_atlas_end(&glfw->atlas, nk_handle_id((int)glfw->ogl.font_tex), &glfw->ogl.null);
if (glfw->atlas.default_font)
nk_style_set_font(&glfw->ctx, &glfw->atlas.default_font->handle);
}
NK_API void
nk_glfw3_new_frame(struct nk_glfw* glfw)
{
int i;
double x, y;
struct nk_context *ctx = &glfw->ctx;
struct GLFWwindow *win = glfw->win;
glfwGetWindowSize(win, &glfw->width, &glfw->height);
glfwGetFramebufferSize(win, &glfw->display_width, &glfw->display_height);
glfw->fb_scale.x = (float)glfw->display_width/(float)glfw->width;
glfw->fb_scale.y = (float)glfw->display_height/(float)glfw->height;
nk_input_begin(ctx);
for (i = 0; i < glfw->text_len; ++i)
nk_input_unicode(ctx, glfw->text[i]);
#ifdef NK_GLFW_GL3_MOUSE_GRABBING
/* optional grabbing behavior */
if (ctx->input.mouse.grab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
else if (ctx->input.mouse.ungrab)
glfwSetInputMode(glfw->win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
} else {
nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_COPY, 0);
nk_input_key(ctx, NK_KEY_PASTE, 0);
nk_input_key(ctx, NK_KEY_CUT, 0);
nk_input_key(ctx, NK_KEY_SHIFT, 0);
}
glfwGetCursorPos(win, &x, &y);
nk_input_motion(ctx, (int)x, (int)y);
#ifdef NK_GLFW_GL3_MOUSE_GRABBING
if (ctx->input.mouse.grabbed) {
glfwSetCursorPos(glfw->win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y);
ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
}
#endif
nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_DOUBLE, (int)glfw->double_click_pos.x, (int)glfw->double_click_pos.y, glfw->is_double_click_down);
nk_input_scroll(ctx, glfw->scroll);
nk_input_end(&glfw->ctx);
glfw->text_len = 0;
glfw->scroll = nk_vec2(0,0);
}
NK_API
void nk_glfw3_shutdown(struct nk_glfw* glfw)
{
nk_font_atlas_clear(&glfw->atlas);
nk_free(&glfw->ctx);
nk_glfw3_device_destroy(glfw);
memset(glfw, 0, sizeof(*glfw));
}
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

4318
source/engine/thirdparty/sokol/sokol_gl.h vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,167 @@
#if defined(SOKOL_IMPL) && !defined(SOKOL_MEMTRACK_IMPL)
#define SOKOL_MEMTRACK_IMPL
#endif
#ifndef SOKOL_MEMTRACK_INCLUDED
/*
sokol_memtrack.h -- memory allocation wrapper to track memory usage
of sokol libraries
Project URL: https://github.com/floooh/sokol
Optionally provide the following defines with your own implementations:
SOKOL_MEMTRACK_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_MEMTRACK_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
If sokol_memtrack.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
USAGE
=====
Just plug the malloc/free wrapper functions into the desc.allocator
struct provided by most sokol header setup functions:
sg_setup(&(sg_desc){
//...
.allocator = {
.alloc = smemtrack_alloc,
.free = smemtrack_free,
}
});
Then call smemtrack_info() to get information about current number
of allocations and overall allocation size:
const smemtrack_info_t info = smemtrack_info();
const int num_allocs = info.num_allocs;
const int num_bytes = info.num_bytes;
Note the sokol_memtrack.h can only track allocations issued by
the sokol headers, not allocations that happen under the hood
in system libraries.
LICENSE
=======
zlib/libpng license
Copyright (c) 2018 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#define SOKOL_MEMTRACK_INCLUDED (1)
#include <stdint.h>
#include <stddef.h> // size_t
#if defined(SOKOL_API_DECL) && !defined(SOKOL_MEMTRACK_API_DECL)
#define SOKOL_MEMTRACK_API_DECL SOKOL_API_DECL
#endif
#ifndef SOKOL_MEMTRACK_API_DECL
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_MEMTRACK_IMPL)
#define SOKOL_MEMTRACK_API_DECL __declspec(dllexport)
#elif defined(_WIN32) && defined(SOKOL_DLL)
#define SOKOL_MEMTRACK_API_DECL __declspec(dllimport)
#else
#define SOKOL_MEMTRACK_API_DECL extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct smemtrack_info_t {
int num_allocs;
int num_bytes;
} smemtrack_info_t;
SOKOL_MEMTRACK_API_DECL smemtrack_info_t smemtrack_info(void);
SOKOL_MEMTRACK_API_DECL void* smemtrack_alloc(size_t size, void* user_data);
SOKOL_MEMTRACK_API_DECL void smemtrack_free(void* ptr, void* user_data);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SOKOL_MEMTRACK_INCLUDED */
/*=== IMPLEMENTATION =========================================================*/
#ifdef SOKOL_MEMTRACK_IMPL
#define SOKOL_MEMTRACK_IMPL_INCLUDED (1)
#include <stdlib.h> // malloc, free
#include <string.h> // memset
#ifndef SOKOL_API_IMPL
#define SOKOL_API_IMPL
#endif
#ifndef SOKOL_DEBUG
#ifndef NDEBUG
#define SOKOL_DEBUG
#endif
#endif
#ifndef _SOKOL_PRIVATE
#if defined(__GNUC__) || defined(__clang__)
#define _SOKOL_PRIVATE __attribute__((unused)) static
#else
#define _SOKOL_PRIVATE static
#endif
#endif
// per-allocation header used to keep track of the allocation size
#define _SMEMTRACK_HEADER_SIZE (16)
static struct {
smemtrack_info_t state;
} _smemtrack;
SOKOL_API_IMPL void* smemtrack_alloc(size_t size, void* user_data) {
(void)user_data;
uint8_t* ptr = (uint8_t*) malloc(size + _SMEMTRACK_HEADER_SIZE);
if (ptr) {
// store allocation size (for allocation size tracking)
*(size_t*)ptr = size;
_smemtrack.state.num_allocs++;
_smemtrack.state.num_bytes += (int) size;
return ptr + _SMEMTRACK_HEADER_SIZE;
}
else {
// allocation failed, return null pointer
return ptr;
}
}
SOKOL_API_IMPL void smemtrack_free(void* ptr, void* user_data) {
(void)user_data;
if (ptr) {
uint8_t* alloc_ptr = ((uint8_t*)ptr) - _SMEMTRACK_HEADER_SIZE;
size_t size = *(size_t*)alloc_ptr;
_smemtrack.state.num_allocs--;
_smemtrack.state.num_bytes -= (int) size;
free(alloc_ptr);
}
}
SOKOL_API_IMPL smemtrack_info_t smemtrack_info(void) {
return _smemtrack.state;
}
#endif /* SOKOL_MEMTRACK_IMPL */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,88 +1,86 @@
#include "timer.h" #include "timer.h"
#include <stdlib.h>
#include "log.h" #include "log.h"
#include <stdlib.h>
#include <stb_ds.h> #include <stb_ds.h>
struct timer *timers; struct timer *timers;
static int first = -1; static int first = -1;
void check_timer(struct timer *t, double dt) void check_timer(struct timer *t, double dt) {
{ if (!t->on)
if (!t->on) return;
return;
t->remain_time -= dt; t->remain_time -= dt;
if (t->remain_time <= 0) { if (t->remain_time <= 0) {
t->cb(t->data); t->cb(t->data);
if (t->repeat) { if (t->repeat) {
t->remain_time = t->interval; t->remain_time = t->interval;
return; return;
}
timer_pause(t);
return;
} }
timer_pause(t);
return;
}
} }
void timer_update(double dt) { void timer_update(double dt) {
for (int i = 0; i < arrlen(timers); i++) for (int i = 0; i < arrlen(timers); i++)
check_timer(&timers[i], dt); check_timer(&timers[i], dt);
} }
int timer_make(double interval, void (*callback)(void *param), void *param, int own) { int timer_make(double interval, void (*callback)(void *param), void *param, int own) {
struct timer new; struct timer new;
new.remain_time = interval; new.remain_time = interval;
new.interval = interval; new.interval = interval;
new.cb = callback; new.cb = callback;
new.data = param; new.data = param;
new.repeat = 1; new.repeat = 1;
new.owndata = own; new.owndata = own;
new.next = -1; new.next = -1;
if (first < 0) { if (first < 0) {
timer_start(&new); timer_start(&new);
arrput(timers, new); arrput(timers, new);
return arrlen(timers)-1; return arrlen(timers) - 1;
} else { } else {
int retid = first; int retid = first;
first = id2timer(first)->next; first = id2timer(first)->next;
*id2timer(retid) = new; *id2timer(retid) = new;
timer_start(id2timer(retid)); timer_start(id2timer(retid));
return retid; return retid;
} }
} }
void timer_pause(struct timer *t) { void timer_pause(struct timer *t) {
if (!t->on) return; if (!t->on) return;
t->on = 0; t->on = 0;
} }
void timer_stop(struct timer *t) { void timer_stop(struct timer *t) {
if (!t->on) return; if (!t->on) return;
t->on = 0; t->on = 0;
t->remain_time = t->interval; t->remain_time = t->interval;
} }
void timer_start(struct timer *t) { void timer_start(struct timer *t) {
if (t->on) return; if (t->on) return;
t->on = 1; t->on = 1;
} }
void timer_remove(int id) { void timer_remove(int id) {
struct timer *t = id2timer(id); struct timer *t = id2timer(id);
if (t->owndata) free(t->data); if (t->owndata) free(t->data);
t->next = first; t->next = first;
first = id; first = id;
} }
void timerr_settime(struct timer *t, double interval) { void timerr_settime(struct timer *t, double interval) {
t->remain_time += (interval - t->interval); t->remain_time += (interval - t->interval);
t->interval = interval; t->interval = interval;
} }
struct timer *id2timer(int id) struct timer *id2timer(int id) {
{ return &timers[id];
return &timers[id];
} }

File diff suppressed because it is too large Load diff

View file

@ -1,52 +1,44 @@
#include "transform.h" #include "transform.h"
#include <string.h> #include <string.h>
struct mTransform MakeTransform(mfloat_t pos[3], mfloat_t rotation[4], float scale) struct mTransform MakeTransform(mfloat_t pos[3], mfloat_t rotation[4], float scale) {
{ struct mTransform newT;
struct mTransform newT; memcpy(newT.position, pos, sizeof(*pos));
memcpy(newT.position, pos, sizeof(*pos)); memcpy(newT.rotation, rotation, sizeof(*rotation));
memcpy(newT.rotation, rotation, sizeof(*rotation)); newT.scale = scale;
newT.scale = scale; return newT;
return newT;
} }
mfloat_t *trans_forward(mfloat_t * res, mfloat_t *trans_forward(mfloat_t *res,
const struct mTransform *const trans) const struct mTransform *const trans) {
{ // YughLog(0, SDL_LOG_PRIORITY_WARN, "Rotation is %f", trans->rotation[0]);
// YughLog(0, SDL_LOG_PRIORITY_WARN, "Rotation is %f", trans->rotation[0]); return vec3_rotate_quat(res, FORWARD, trans->rotation);
return vec3_rotate_quat(res, FORWARD, trans->rotation);
} }
mfloat_t *trans_back(mfloat_t * res, const struct mTransform *trans) mfloat_t *trans_back(mfloat_t *res, const struct mTransform *trans) {
{ return vec3_rotate_quat(res, BACK, trans->rotation);
return vec3_rotate_quat(res, BACK, trans->rotation);
} }
mfloat_t *trans_up(mfloat_t * res, const struct mTransform *trans) mfloat_t *trans_up(mfloat_t *res, const struct mTransform *trans) {
{ return vec3_rotate_quat(res, UP, trans->rotation);
return vec3_rotate_quat(res, UP, trans->rotation);
} }
mfloat_t *trans_down(mfloat_t * res, const struct mTransform *trans) mfloat_t *trans_down(mfloat_t *res, const struct mTransform *trans) {
{ return vec3_rotate_quat(res, DOWN, trans->rotation);
return vec3_rotate_quat(res, DOWN, trans->rotation);
} }
mfloat_t *trans_right(mfloat_t * res, const struct mTransform *trans) mfloat_t *trans_right(mfloat_t *res, const struct mTransform *trans) {
{ return vec3_rotate_quat(res, RIGHT, trans->rotation);
return vec3_rotate_quat(res, RIGHT, trans->rotation);
} }
mfloat_t *trans_left(mfloat_t * res, const struct mTransform *trans) mfloat_t *trans_left(mfloat_t *res, const struct mTransform *trans) {
{ return vec3_rotate_quat(res, LEFT, trans->rotation);
return vec3_rotate_quat(res, LEFT, trans->rotation);
} }
#include "nuke.h" #include "nuke.h"
void trans_drawgui(struct mTransform *T) void trans_drawgui(struct mTransform *T) {
{ nuke_property_float3("Position", -1000.f, T->position, 1000.f, 1.f, 1.f);
nuke_property_float3("Position", -1000.f, T->position, 1000.f, 1.f, 1.f); nuke_property_float3("Rotation", 0.f, T->rotation, 360.f, 1.f, 0.1f);
nuke_property_float3("Rotation", 0.f, T->rotation, 360.f, 1.f, 0.1f); nuke_property_float("Scale", 0.f, &T->scale, 1000.f, 0.1f, 0.1f);
nuke_property_float("Scale", 0.f, &T->scale, 1000.f, 0.1f, 0.1f);
} }

View file

@ -1,12 +1,12 @@
#include "window.h" #include "window.h"
#include <string.h>
#include "texture.h"
#include "log.h"
#include <stdlib.h>
#include <stdio.h>
#include "input.h" #include "input.h"
#include "script.h" #include "log.h"
#include "nuke.h" #include "nuke.h"
#include "script.h"
#include "texture.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "openglrender.h" #include "openglrender.h"
@ -18,277 +18,248 @@ static struct window *windows = NULL;
struct Texture *icon = NULL; struct Texture *icon = NULL;
int is_win(struct window *s, GLFWwindow *w) int is_win(struct window *s, GLFWwindow *w) {
{ return s->window == w;
return s->window == w;
} }
void window_size_callback(GLFWwindow *w, int width, int height) void window_size_callback(GLFWwindow *w, int width, int height) {
{
} }
struct window *winfind(GLFWwindow *w) struct window *winfind(GLFWwindow *w) {
{ for (int i = 0; i < arrlen(windows); i++) {
for (int i = 0; i < arrlen(windows); i++) { if (windows[i].window == w)
if (windows[i].window == w) return &windows[i];
return &windows[i]; }
}
return NULL;
}
void window_iconify_callback(GLFWwindow *w, int iconified) {
struct window *win = winfind(w);
win->iconified = iconified;
}
void window_focus_callback(GLFWwindow *w, int focused) {
struct window *win = winfind(w);
win->mouseFocus = focused;
}
void window_maximize_callback(GLFWwindow *w, int maximized) {
struct window *win = winfind(w);
win->minimized = !maximized;
}
void window_framebuffer_size_cb(GLFWwindow *w, int width, int height) {
struct window *win = winfind(w);
win->width = width;
win->height = height;
window_makecurrent(win);
win->render = 1;
}
void window_close_callback(GLFWwindow *w) {
quit();
}
struct window *MakeSDLWindow(const char *name, int width, int height, uint32_t flags) {
if (arrcap(windows) == 0)
arrsetcap(windows, 5);
GLFWwindow *sharewin = mainwin == NULL ? NULL : mainwin->window;
if (sharewin) return sharewin;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_SAMPLES,1);
struct window w = {
.width = width,
.height = height,
.id = arrlen(windows),
.window = glfwCreateWindow(width, height, name, NULL, sharewin)};
if (!w.window) {
YughError("Couldn't make GLFW window\n", 1);
return NULL; return NULL;
}
glfwMakeContextCurrent(w.window);
// int version = gladLoadGL(glfwGetProcAddress);
// if (!version) {
// YughError("Failed to initialize OpenGL context.");
// exit(1);
// }
YughInfo("Loaded OpenGL %d.%d", 3, 3);
glfwSwapInterval(1);
// Set callbacks
glfwSetWindowCloseCallback(w.window, window_close_callback);
glfwSetWindowSizeCallback(w.window, window_size_callback);
glfwSetFramebufferSizeCallback(w.window, window_framebuffer_size_cb);
glfwSetWindowFocusCallback(w.window, window_focus_callback);
glfwSetKeyCallback(w.window, win_key_callback);
arrput(windows, w);
if (arrlen(windows) == 1)
mainwin = &windows[0];
return &arrlast(windows);
} }
void window_iconify_callback(GLFWwindow *w, int iconified) void window_set_icon(const char *png) {
{
struct window *win = winfind(w);
win->iconified = iconified;
}
void window_focus_callback(GLFWwindow *w, int focused)
{
struct window *win = winfind(w);
win->mouseFocus = focused;
}
void window_maximize_callback(GLFWwindow *w, int maximized)
{
struct window *win = winfind(w);
win->minimized = !maximized;
}
void window_framebuffer_size_cb(GLFWwindow *w, int width, int height)
{
struct window *win = winfind(w);
win->width = width;
win->height = height;
window_makecurrent(win);
win->render = 1;
}
void window_close_callback(GLFWwindow *w)
{
quit();
}
struct window *MakeSDLWindow(const char *name, int width, int height, uint32_t flags)
{
if (arrcap(windows) == 0)
arrsetcap(windows, 5);
GLFWwindow *sharewin = mainwin == NULL ? NULL : mainwin->window;
if (sharewin) return sharewin;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
struct window w = {
.width = width,
.height = height,
.id = arrlen(windows),
.window = glfwCreateWindow(width, height, name, NULL, sharewin) };
if (!w.window) {
YughError("Couldn't make GLFW window\n", 1);
return NULL;
}
glfwMakeContextCurrent(w.window);
// int version = gladLoadGL(glfwGetProcAddress);
// if (!version) {
// YughError("Failed to initialize OpenGL context.");
// exit(1);
// }
YughInfo("Loaded OpenGL %d.%d", 3,3);
glfwSwapInterval(1);
// Set callbacks
glfwSetWindowCloseCallback(w.window, window_close_callback);
glfwSetWindowSizeCallback(w.window, window_size_callback);
glfwSetFramebufferSizeCallback(w.window, window_framebuffer_size_cb);
glfwSetWindowFocusCallback(w.window, window_focus_callback);
glfwSetKeyCallback(w.window, win_key_callback);
// nuke_init(&w);
arrput(windows, w);
if (arrlen(windows) == 1)
mainwin = &windows[0];
return &arrlast(windows);
}
void window_set_icon(const char *png)
{
icon = texture_pullfromfile(png); icon = texture_pullfromfile(png);
window_seticon(mainwin, icon); window_seticon(mainwin, icon);
} }
void window_destroy(struct window *w) void window_destroy(struct window *w) {
{ glfwDestroyWindow(w->window);
glfwDestroyWindow(w->window); arrdelswap(windows, w->id);
arrdelswap(windows, w->id);
} }
struct window *window_i(int index) { struct window *window_i(int index) {
return &windows[index]; return &windows[index];
} }
void window_handle_event(struct window *w) void window_handle_event(struct window *w) {
{ /*
/* if (e->type == SDL_WINDOWEVENT && e->window.windowID == w->id) { // TODO: Check ptr direct?
if (e->type == SDL_WINDOWEVENT && e->window.windowID == w->id) { // TODO: Check ptr direct? switch (e->window.event) {
switch (e->window.event) { case SDL_WINDOWEVENT_SHOWN:
case SDL_WINDOWEVENT_SHOWN: YughLog(0, SDL_LOG_PRIORITY_INFO, "Showed window %d.", w->id);
YughLog(0, SDL_LOG_PRIORITY_INFO, "Showed window %d.", w->id); w->shown = true;
w->shown = true; break;
break;
case SDL_WINDOWEVENT_HIDDEN: case SDL_WINDOWEVENT_HIDDEN:
w->shown = false; w->shown = false;
YughLog(0, SDL_LOG_PRIORITY_INFO, "Hid window %d.", w->id); YughLog(0, SDL_LOG_PRIORITY_INFO, "Hid window %d.", w->id);
break; break;
case SDL_WINDOWEVENT_SIZE_CHANGED: case SDL_WINDOWEVENT_SIZE_CHANGED:
w->width = e->window.data1; w->width = e->window.data1;
w->height = e->window.data2; w->height = e->window.data2;
YughLog(0, SDL_LOG_PRIORITY_INFO, YughLog(0, SDL_LOG_PRIORITY_INFO,
"Changed size of window %d: width %d, height %d.", "Changed size of window %d: width %d, height %d.",
w->id, w->width, w->height); w->id, w->width, w->height);
window_makecurrent(w); window_makecurrent(w);
w->render = true; w->render = true;
break; break;
case SDL_WINDOWEVENT_EXPOSED: case SDL_WINDOWEVENT_EXPOSED:
YughLog(0, SDL_LOG_PRIORITY_INFO, "Exposed window %d.", w->id); YughLog(0, SDL_LOG_PRIORITY_INFO, "Exposed window %d.", w->id);
w->render = true; w->render = true;
break; break;
case SDL_WINDOWEVENT_ENTER: case SDL_WINDOWEVENT_ENTER:
YughLog(0, SDL_LOG_PRIORITY_INFO, "Entered window %d.", w->id); YughLog(0, SDL_LOG_PRIORITY_INFO, "Entered window %d.", w->id);
w->mouseFocus = true; w->mouseFocus = true;
SDL_RaiseWindow(w->window); SDL_RaiseWindow(w->window);
break; break;
case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_LEAVE:
YughLog(0, SDL_LOG_PRIORITY_INFO, "Left window %d.", w->id); YughLog(0, SDL_LOG_PRIORITY_INFO, "Left window %d.", w->id);
w->mouseFocus = false; w->mouseFocus = false;
break; break;
case SDL_WINDOWEVENT_FOCUS_LOST: case SDL_WINDOWEVENT_FOCUS_LOST:
YughLog(0, SDL_LOG_PRIORITY_INFO, YughLog(0, SDL_LOG_PRIORITY_INFO,
"Lost focus on window %d.", w->id); "Lost focus on window %d.", w->id);
w->keyboardFocus = false; w->keyboardFocus = false;
break; break;
case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_FOCUS_GAINED:
YughLog(0, SDL_LOG_PRIORITY_INFO, YughLog(0, SDL_LOG_PRIORITY_INFO,
"Gained focus on window %d.", w->id); "Gained focus on window %d.", w->id);
w->keyboardFocus = true; w->keyboardFocus = true;
break; break;
case SDL_WINDOWEVENT_MINIMIZED: case SDL_WINDOWEVENT_MINIMIZED:
YughLog(0, SDL_LOG_PRIORITY_INFO, YughLog(0, SDL_LOG_PRIORITY_INFO,
"Minimized window %d.", w->id); "Minimized window %d.", w->id);
w->minimized = true; w->minimized = true;
break; break;
case SDL_WINDOWEVENT_MAXIMIZED: case SDL_WINDOWEVENT_MAXIMIZED:
YughLog(0, SDL_LOG_PRIORITY_INFO, YughLog(0, SDL_LOG_PRIORITY_INFO,
"Maximized window %d.", w->id); "Maximized window %d.", w->id);
w->minimized = false; w->minimized = false;
break; break;
case SDL_WINDOWEVENT_RESTORED: case SDL_WINDOWEVENT_RESTORED:
YughLog(0, SDL_LOG_PRIORITY_INFO, YughLog(0, SDL_LOG_PRIORITY_INFO,
"Restored window %d.", w->id); "Restored window %d.", w->id);
w->minimized = false; w->minimized = false;
break; break;
case SDL_WINDOWEVENT_CLOSE: case SDL_WINDOWEVENT_CLOSE:
YughLog(0, SDL_LOG_PRIORITY_INFO, "Closed window %d.", w->id); YughLog(0, SDL_LOG_PRIORITY_INFO, "Closed window %d.", w->id);
break; break;
} }
} }
*/ */
} }
void window_all_handle_events() void window_all_handle_events() {
{ for (int i = 0; i < arrlen(windows); i++)
for (int i = 0; i < arrlen(windows); i++) window_handle_event(&windows[i]);
window_handle_event(&windows[i]);
} }
void window_makefullscreen(struct window *w) void window_makefullscreen(struct window *w) {
{ if (!w->fullscreen)
if (!w->fullscreen) window_togglefullscreen(w);
window_togglefullscreen(w);
} }
void window_unfullscreen(struct window *w) void window_unfullscreen(struct window *w) {
{ if (w->fullscreen)
if (w->fullscreen) window_togglefullscreen(w);
window_togglefullscreen(w);
} }
void window_togglefullscreen(struct window *w) void window_togglefullscreen(struct window *w) {
{ w->fullscreen = !w->fullscreen;
w->fullscreen = !w->fullscreen;
if (w->fullscreen) {
glfwMaximizeWindow(w->window);
} else {
glfwRestoreWindow(w->window);
}
if (w->fullscreen) {
glfwMaximizeWindow(w->window);
} else {
glfwRestoreWindow(w->window);
}
} }
void window_makecurrent(struct window *w) void window_makecurrent(struct window *w) {
{
if (w->window != glfwGetCurrentContext())
glfwMakeContextCurrent(w->window);
glViewport(0, 0, w->width, w->height);
if (w->window != glfwGetCurrentContext())
glfwMakeContextCurrent(w->window);
glViewport(0, 0, w->width, w->height);
} }
void window_swap(struct window *w) {
glfwSwapBuffers(w->window);
void window_swap(struct window *w)
{
glfwSwapBuffers(w->window);
} }
void window_seticon(struct window *w, struct Texture *icon) void window_seticon(struct window *w, struct Texture *icon) {
{
static GLFWimage images[1]; static GLFWimage images[1];
images[0].width = icon->width; images[0].width = icon->width;
images[0].height = icon->height; images[0].height = icon->height;
images[0].pixels = icon->data; images[0].pixels = icon->data;
glfwSetWindowIcon(w->window, 1, images); glfwSetWindowIcon(w->window, 1, images);
} }
int window_hasfocus(struct window *w) int window_hasfocus(struct window *w) {
{ return glfwGetWindowAttrib(w->window, GLFW_FOCUSED);
return glfwGetWindowAttrib(w->window, GLFW_FOCUSED);
} }
void window_render(struct window *w) { void window_render(struct window *w) {
window_makecurrent(w); window_makecurrent(w);
openglRender(w); openglRender(w);
window_swap(w); window_swap(w);
} }
void window_renderall() { void window_renderall() {
//arrwalk(windows, window_render); // arrwalk(windows, window_render);
for (int i = 0; i < arrlen(windows); i++) for (int i = 0; i < arrlen(windows); i++)
window_render(&windows[i]); window_render(&windows[i]);
} }

View file

@ -1,13 +1,12 @@
#include "yugine.h" #include "yugine.h"
#include "camera.h" #include "camera.h"
#include "window.h"
#include "engine.h" #include "engine.h"
#include "font.h"
#include "gameobject.h"
#include "input.h" #include "input.h"
#include "openglrender.h" #include "openglrender.h"
#include "gameobject.h" #include "window.h"
#include "font.h"
#define MINIAUDIO_IMPLEMENTATION #define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h" #include "miniaudio.h"
@ -16,8 +15,8 @@
#include "quickjs/quickjs.h" #include "quickjs/quickjs.h"
#include "script.h"
#include "ffi.h" #include "ffi.h"
#include "script.h"
#include "log.h" #include "log.h"
#include <stdio.h> #include <stdio.h>
@ -25,28 +24,26 @@
#include "2dphysics.h" #include "2dphysics.h"
#include <execinfo.h>
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#include <execinfo.h>
#include "string.h" #include "string.h"
#define SOKOL_TRACE_HOOKS #define SOKOL_TRACE_HOOKS
#define SOKOL_GFX_IMPL #define SOKOL_GFX_IMPL
#define SOKOL_GLCORE33 #define SOKOL_GLCORE33
#include "sokol/sokol_gfx.h" #include "sokol/sokol_gfx.h"
int physOn = 0; int physOn = 0;
double renderlag = 0; double renderlag = 0;
double physlag = 0; double physlag = 0;
double updatelag = 0; double updatelag = 0;
double renderMS = 1/165.f; double renderMS = 1 / 165.f;
double physMS = 1/120.f; double physMS = 1 / 120.f;
double updateMS = 1/60.f; double updateMS = 1 / 60.f;
static int ed = 1; static int ed = 1;
static int sim_play = 0; static int sim_play = 0;
@ -65,39 +62,37 @@ int fps;
#define SIM_PAUSE 2 #define SIM_PAUSE 2
#define SIM_STEP 3 #define SIM_STEP 3
void print_stacktrace() void print_stacktrace() {
{ void *ents[512];
void *ents[512]; size_t size;
size_t size;
size = backtrace(ents, 512); size = backtrace(ents, 512);
YughCritical("====================BACKTRACE===================="); YughCritical("====================BACKTRACE====================");
char **stackstr = backtrace_symbols(ents, size); char **stackstr = backtrace_symbols(ents, size);
YughInfo("Stack size is %d.", size); YughInfo("Stack size is %d.", size);
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
YughCritical(stackstr[i]); YughCritical(stackstr[i]);
js_stacktrace(); js_stacktrace();
} }
void seghandle(int sig) { void seghandle(int sig) {
#ifdef __linux__ #ifdef __linux__
if (strsignal(sig)) if (strsignal(sig))
YughCritical("CRASH! Signal: %s.", strsignal(sig)); YughCritical("CRASH! Signal: %s.", strsignal(sig));
print_stacktrace(); print_stacktrace();
exit(1); exit(1);
#endif #endif
} }
void compile_script(const char *file) void compile_script(const char *file) {
{
const char *script = slurp_text(file); const char *script = slurp_text(file);
JSValue obj = JS_Eval(js, script, strlen(script), file, JS_EVAL_FLAG_COMPILE_ONLY|JS_EVAL_TYPE_GLOBAL); JSValue obj = JS_Eval(js, script, strlen(script), file, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_GLOBAL);
size_t out_len; size_t out_len;
uint8_t *out; uint8_t *out;
out = JS_WriteObject(js, &out_len, obj, JS_WRITE_OBJ_BYTECODE); out = JS_WriteObject(js, &out_len, obj, JS_WRITE_OBJ_BYTECODE);
@ -107,159 +102,157 @@ void compile_script(const char *file)
fclose(f); fclose(f);
} }
void sg_logging(const char *tag, uint32_t lvl, uint32_t id, const char *msg, uint32_t line, const char *file, void *data) void sg_logging(const char *tag, uint32_t lvl, uint32_t id, const char *msg, uint32_t line, const char *file, void *data) {
{
mYughLog(0, 1, line, file, "tag: %s, msg: %s", tag, msg); mYughLog(0, 1, line, file, "tag: %s, msg: %s", tag, msg);
} }
int main(int argc, char **args) { int main(int argc, char **args) {
int logout = 1; int logout = 1;
ed = 1; ed = 1;
script_startup(); script_startup();
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
if (args[i][0] == '-') { if (args[i][0] == '-') {
switch(args[i][1]) { switch (args[i][1]) {
case 'p': case 'p':
ed = 0; ed = 0;
break; break;
case 'l': case 'l':
if (i+1 < argc && args[i+1][0] != '-') { if (i + 1 < argc && args[i + 1][0] != '-') {
log_setfile(args[i+1]); log_setfile(args[i + 1]);
i++; i++;
continue; continue;
} } else {
else { YughError("Expected a file for command line arg '-l'.");
YughError("Expected a file for command line arg '-l'."); exit(1);
exit(1);
}
case 'v':
printf("Yugine version %s, %s build.\n", VER, INFO);
printf("Copyright 2022-2023 odplot productions LLC.\n");
exit(1);
break;
case 's':
compile_script(args[2]);
exit(0);
case 'm':
logLevel = atoi(args[2]);
break;
case 'h':
printf("-l Set log file\n");
printf("-p Launch engine in play mode instead of editor mode\n");
printf("-v Display engine info\n");
printf("-c Redirect logging to console\n");
exit(0);
break;
case 'c':
logout = 0;
break;
}
} }
case 'v':
printf("Yugine version %s, %s build.\n", VER, INFO);
printf("Copyright 2022-2023 odplot productions LLC.\n");
exit(1);
break;
case 's':
compile_script(args[2]);
exit(0);
case 'm':
logLevel = atoi(args[2]);
break;
case 'h':
printf("-l Set log file\n");
printf("-p Launch engine in play mode instead of editor mode\n");
printf("-v Display engine info\n");
printf("-c Redirect logging to console\n");
exit(0);
break;
case 'c':
logout = 0;
break;
}
} }
}
#if DBG #if DBG
if (logout) { if (logout) {
time_t now = time(NULL); time_t now = time(NULL);
char fname[100]; char fname[100];
snprintf(fname, 100, "yugine-%d.log", now); snprintf(fname, 100, "yugine-%d.log", now);
log_setfile(fname); log_setfile(fname);
} }
YughInfo("Starting yugine version %s.", VER); YughInfo("Starting yugine version %s.", VER);
FILE *sysinfo = NULL;
/* sysinfo = popen("uname -a", "r");
if (!sysinfo) {
YughWarn("Failed to get sys info.");
} else {
log_cat(sysinfo);
pclose(sysinfo);
}*/
signal(SIGSEGV, seghandle);
signal(SIGABRT, seghandle);
signal(SIGFPE, seghandle);
signal(SIGBUS, seghandle);
FILE *sysinfo = NULL;
/* sysinfo = popen("uname -a", "r");
if (!sysinfo) {
YughWarn("Failed to get sys info.");
} else {
log_cat(sysinfo);
pclose(sysinfo);
}*/
signal(SIGSEGV, seghandle);
signal(SIGABRT, seghandle);
signal(SIGFPE, seghandle);
signal(SIGBUS, seghandle);
#endif #endif
engine_init(); engine_init();
const GLFWvidmode *vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); const GLFWvidmode *vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
YughInfo("Refresh rate is %d", vidmode->refreshRate); YughInfo("Refresh rate is %d", vidmode->refreshRate);
renderMS = 1.0/vidmode->refreshRate; renderMS = 1.0 / vidmode->refreshRate;
sg_setup(&(sg_desc){ sg_setup(&(sg_desc){
.logger = { .logger = {
.func = sg_logging, .func = sg_logging,
.user_data = NULL, .user_data = NULL,
}, },
}); .buffer_pool_size = 1024,
.context.sample_count = 1,
input_init(); });
openglInit();
if (ed) input_init();
script_dofile("scripts/editor.js"); openglInit();
else
script_dofile("scripts/play.js");
while (!want_quit()) { if (ed)
double elapsed = glfwGetTime() - lastTick; script_dofile("scripts/editor.js");
deltaT = elapsed; else
lastTick = glfwGetTime(); script_dofile("scripts/play.js");
double wait = fmax(0, renderMS-elapsed);
input_poll(wait);
window_all_handle_events();
framems[framei++] = elapsed; while (!want_quit()) {
double elapsed = glfwGetTime() - lastTick;
deltaT = elapsed;
lastTick = glfwGetTime();
double wait = fmax(0, renderMS - elapsed);
input_poll(wait);
window_all_handle_events();
if (framei == FPSBUF) framei = 0; framems[framei++] = elapsed;
if (sim_play == SIM_PLAY || sim_play == SIM_STEP) { if (framei == FPSBUF) framei = 0;
timer_update(elapsed * timescale);
physlag += elapsed;
call_updates(elapsed * timescale);
while (physlag >= physMS) {
phys_step = 1;
physlag -= physMS;
phys2d_update(physMS * timescale);
call_physics(physMS * timescale);
if (sim_play == SIM_STEP) sim_pause();
phys_step = 0;
}
}
renderlag += elapsed; if (sim_play == SIM_PLAY || sim_play == SIM_STEP) {
timer_update(elapsed * timescale);
if (renderlag >= renderMS) { physlag += elapsed;
renderlag -= renderMS; call_updates(elapsed * timescale);
window_renderall(); while (physlag >= physMS) {
} phys_step = 1;
physlag -= physMS;
gameobjects_cleanup(); phys2d_update(physMS * timescale);
call_physics(physMS * timescale);
if (sim_play == SIM_STEP) sim_pause();
phys_step = 0;
}
} }
return 0; renderlag += elapsed;
if (renderlag >= renderMS) {
renderlag -= renderMS;
window_renderall();
}
gameobjects_cleanup();
}
return 0;
} }
int frame_fps() int frame_fps() {
{ double fpsms = 0;
double fpsms = 0; for (int i = 0; i < FPSBUF; i++) {
for (int i = 0; i < FPSBUF; i++) { fpsms += framems[i];
fpsms += framems[i]; }
}
return FPSBUF / fpsms; return FPSBUF / fpsms;
} }
int sim_playing() { return sim_play == SIM_PLAY; } int sim_playing() { return sim_play == SIM_PLAY; }
@ -275,19 +268,19 @@ void sim_pause() {
} }
void sim_stop() { void sim_stop() {
/* Revert starting state of everything from sim_start */ /* Revert starting state of everything from sim_start */
sim_play = SIM_STOP; sim_play = SIM_STOP;
} }
int phys_stepping() { return phys_step; } int phys_stepping() { return phys_step; }
void sim_step() { void sim_step() {
if (sim_paused()) { if (sim_paused()) {
YughInfo("Step"); YughInfo("Step");
sim_play = SIM_STEP; sim_play = SIM_STEP;
} }
} }
void set_timescale(float val) { void set_timescale(float val) {
timescale = val; timescale = val;
} }

View file

@ -1,6 +0,0 @@
#version 330 core
void main()
{
// gl_FragDepth = gl_FragCoord.z;
}

View file

@ -3,24 +3,27 @@ in vec2 coords;
out vec4 color; out vec4 color;
uniform float radius; //in int thickness;
uniform int thickness; in float radius;
uniform vec3 dbgColor; //in bool fill;
uniform bool fill; in vec3 fcolor;
uniform float zoom; in vec2 pos;
void main() void main()
{ {
int thickness = 1;
bool fill = false;
// int tt = thickness + 1; // int tt = thickness + 1;
float R1 = 1.f; float R1 = 1.f;
float R2 = 1.f - (thickness*zoom / radius); // float R2 = 1.f - (thickness*zoom / radius);
float R2 = 1.f - (thickness/radius);
float dist = sqrt(dot(coords, coords)); float dist = sqrt(dot(coords, coords));
if (dist >= R2 && dist <= R1) if (dist >= R2 && dist <= R1)
color = vec4(dbgColor, 1.f); color = vec4(fcolor, 1.f);
else if (dist < R2) else if (dist < R2)
color = vec4(dbgColor, 0.1f); color = vec4(fcolor, 0.1f);
else else
discard; discard;
} }

View file

@ -1,12 +1,21 @@
#version 330 core #version 330 core
layout (location = 0) in vec4 vertex; layout (location = 0) in vec2 vertex;
layout (location = 1) in vec3 acolor;
layout (location = 2) in vec2 apos;
layout (location = 3) in float aradius;
layout (location = 4) in float afill;
out vec2 coords; out vec2 coords;
out float radius;
out vec3 fcolor;
uniform mat4 proj; uniform mat4 proj;
uniform vec2 res;
void main() void main()
{ {
gl_Position = proj * vec4(vertex.xy, 0.0, 1.0); gl_Position = proj * vec4((vertex * aradius) + apos, 0.0, 1.0);
coords = vertex.zw; coords = vertex.xy;
fcolor = acolor;
radius = aradius;
} }

View file

@ -0,0 +1,26 @@
#version 330 core
in vec2 TexCoords;
out vec4 frag_color;
uniform sampler2D diffuse_texture;
void main()
{
vec4 color = texture(diffuse_texture, TexCoords);
// float avg = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
// frag_color = vec4(avg,avg,avg,1.0);
float lc = 720.0/2.0;
float line = TexCoords.y * lc;
float line_intensity = mod(float(line),2);
float off = line_intensity * 0.0005;
vec4 shift = vec4(off,0,0,0);
vec4 color_shift = vec4(0.001,0,0,0);
float r = color.r + color_shift.r + shift.r;
float g = color.g - color_shift.g + shift.g;
float b = color.b;
frag_color = vec4(r, g*0.99, b, 1.0) * clamp(line_intensity, 0.85, 1.0);
frag_color = texture(diffuse_texture, TexCoords);
}

View file

@ -0,0 +1,104 @@
#version 330 core
in vec2 tex_coords;
in vec3 normal;
in vec3 frag_pos;
in vec4 frag_pos_light;
out vec4 frag_color;
uniform sampler2D diffuse;
uniform sampler2D normmap;
uniform sampler2D shadow_map;
uniform vec3 point_pos;
uniform vec3 dir_dir;
uniform vec3 view_pos;
uniform vec3 spot_pos;
uniform vec3 spot_dir;
/* Ambient light */
float amb_str = 0.3;
vec3 amb_color = vec3(1,1,1);
float spec_str = 0.5;
/* point */
float constant = 1;
float linear = 0.09;
float quad = 0.032;
/* spotlight */
float cutoff = 12.5; /* cutoff in radians */
float outer_cutoff = 17.5;
vec3 norm = vec3(0,0,0);
vec3 view = vec3(0,0,0);
float light_str(vec3 dir)
{
float d = max(dot(norm, dir), 0.0);
vec3 refl = reflect(-dir, norm);
float s = pow(max(dot(view,refl), 0.0), 32);
return s+d;
}
float shadow_calc(vec4 fg)
{
vec3 pc = fg.xyz / fg.w;
pc = pc * 0.5 + 0.5;
if (pc.z > 1.0)
return 0.0;
float closest_depth = texture(shadow_map, pc.xy).r;
float cur_depth = pc.z;
vec3 light_dir = normalize(vec3(4,100,20) - frag_pos); /* light pos */
float bias = max(0.05 * (1 - dot(norm, light_dir)), 0.005);
return cur_depth - bias > closest_depth ? 1.0 : 0.0;
float s;
vec2 texel_size = 1 / textureSize(shadow_map, 0);
for (int x = -1; x <= 1; ++x) {
for (int y = -1; y <= 1; ++y) {
float pcf_depth = texture(shadow_map, pc.xy + vec2(x,y) * texel_size).r;
s += cur_depth - bias > pcf_depth ? 1.0 : 0.0;
}
}
s /= 9.0;
return s;
}
void main() {
norm = normalize(normal);
view = normalize(view_pos - frag_pos);
float point_amt = light_str(normalize(point_pos-frag_pos));
float dist = length(point_pos - frag_pos);
float atten = 1.0 / (constant + linear * dist + quad * (dist*dist));
point_amt *= atten;
float dir_amt = light_str(normalize(-dir_dir));
vec3 spot_dir = normalize(spot_pos - frag_pos);
float theta = dot(spot_dir, normalize(-spot_dir));
float spot_amt = 0;
float epsilon = cutoff - outer_cutoff;
if (theta > cutoff) {
float intensity = clamp((theta - outer_cutoff)/epsilon,0.0,1.0);
spot_amt = light_str(spot_dir) * intensity;
}
vec4 mm = texture(diffuse,tex_coords);
float shadow = shadow_calc(frag_pos_light);
vec3 res = mm.rgb * (amb_str + (point_amt + dir_amt) * (1 - shadow));
frag_color = vec4(res, mm.a);
}

View file

@ -0,0 +1,23 @@
#version 330 core
layout (location=0) in vec3 a_pos;
layout (location=1) in vec2 a_tex_coords;
layout (location=2) in vec3 a_norm;
out vec2 tex_coords;
out vec3 normal;
out vec3 frag_pos;
out vec4 frag_pos_light;
uniform mat4 vp;
uniform mat4 model;
uniform mat4 proj;
uniform mat4 lsm;
void main() {
frag_pos = vec3(model * vec4(a_pos, 1.0));
gl_Position = proj * vp * vec4(frag_pos, 1.0);
tex_coords = a_tex_coords;
normal = mat3(transpose(inverse(model))) * a_norm;
frag_pos_light = lsm * vec4(frag_pos, 1.0);
}

View file

@ -1,19 +1,27 @@
#version 330 #version 330
out vec4 color; out vec4 frag_color;
in vec2 apos; in vec2 apos;
vec2 bpos; vec2 bpos;
uniform int thickness; uniform float thickness; /* thickness in pixels */
uniform int span; uniform float span;
uniform vec3 color;
void main(void) void main(void)
{ {
float t = thickness / 2.f; float t = thickness / span;
bpos.x = mod(apos.x, span); t /= 2.0;
bpos.y = mod(apos.y, span); bpos.x = mod(apos.x, span) / span;
bpos.y = mod(apos.y, span) / span;
bpos.x -= t;
bpos.y -= t;
if (!(bpos.x <= t || bpos.x >= (span - t) || bpos.y <= t || bpos.y >= (span - t))) float comp = min(bpos.x, bpos.y);
discard;
color = vec4(0.4f, 0.7f, 0.2f, 0.3f); if (comp > t)
} discard;
comp += t;
frag_color = vec4(color, 1.0);
}

View file

@ -1,17 +1,20 @@
#version 330 #version 330
layout (location = 0) in vec2 pos; layout (location = 0) in vec2 pos;
out vec2 apos;
uniform vec2 offset; out vec2 apos;
layout (std140) uniform Projection { layout (std140) uniform Projection {
mat4 projection; mat4 projection;
}; };
uniform vec2 offset;
void main() void main()
{ {
vec4 ipos = inverse(projection) * vec4(pos, 0.f, 1.f); // vec4 ipos = inverse(projection) * vec4(pos, 0.f, 1.f);
apos = ipos.xy + offset; apos = pos * vec2(600, 360);
// apos = pos + offset;
gl_Position = vec4(pos, 0.f, 1.f); gl_Position = vec4(pos, 0.f, 1.f);
} }

View file

@ -6,5 +6,5 @@ uniform float alpha;
void main() void main()
{ {
color = vec4(linecolor, alpha); color = vec4(1.f,1.f,1.f,1.f);
} }

View file

@ -1,11 +1,9 @@
#version 330 #version 330
layout (location = 0) in vec2 pos; layout (location = 0) in vec2 pos;
layout (std140) uniform Projection { uniform mat4 proj;
mat4 projection;
};
void main() void main()
{ {
gl_Position = projection * vec4(pos, 0.f, 1.f); gl_Position = proj * vec4(pos, 0.f, 1.f);
} }

View file

@ -0,0 +1,8 @@
#version 330 core
out float frag_color;
void main()
{
// frag_color = encode_depth(gl_FragCoord.z);
frag_color = gl_FragCoord.z;
}

View file

@ -8,11 +8,8 @@ uniform sampler2D text;
void main() void main()
{ {
color = vec4(fColor.xyz, texture(text, TexCoords).r);
// color = vec4(fColor.xyz, texture(text, TexCoords).r); // color = vec4(1.f, 1.f, 1.f, texture(text, TexCoords).r);
color = vec4(1.f,1.f,1.f, texture(text, TexCoords).r);
if (color.a <= 0.1f) if (color.a <= 0.1f)
discard; discard;
} }