Files
RCBASIC4/rcbasic_runtime/rc_gfx_core.h
n00b 9cac24402e Finished Tiling System
* Finished working on tiling
* Changed how sprite layers work. Sprite layers are now not confined to the limits of the actual canvas but instead will decide where to draw each sprite based on the canvas offset and the sprites location
2024-10-21 18:35:13 -04:00

891 lines
29 KiB
C++

#ifndef RC_GFX_CORE_H_INCLUDED
#define RC_GFX_CORE_H_INCLUDED
#ifdef RC_ANDROID
#include "SDL.h"
#include "btBulletDynamicsCommon.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#else
#include <SDL2/SDL.h>
#include <bullet/btBulletDynamicsCommon.h>
#include <BulletSoftBody/btSoftRigidDynamicsWorld.h>
#endif // _IRR_ANDROID_PLATFORM_
#include <irrlicht.h>
#include <iostream>
#include <sstream>
#include <string>
#include <locale>
#include <codecvt>
#include <cmath>
#include <set>
#include "gui_freetype_font.h"
#include "rc_utf8.h"
#include "camera.h"
#include <box2d/box2d.h>
#include "rc_sprite2D.h"
#include <irrBullet.h>
#ifdef RC_ANDROID
#include "an8parser.h"
#else
#include <an8parser.h>
#endif
using namespace irr;
using namespace core;
using namespace video;
using namespace scene;
#define MAX_JOYSTICKS 32
#define MAX_FINGERS 10
#define MAX_ACCELS 32
#define MAX_GYROS 32
SDL_Joystick * rc_joystick[MAX_JOYSTICKS];
int rc_joy_axis[MAX_JOYSTICKS][100];
int rc_numJoysticks = 0;
int rc_joybutton[MAX_JOYSTICKS][100];
SDL_JoystickID rc_joyID[MAX_JOYSTICKS];
SDL_Joystick * tmp_joy;
SDL_JoystickID tmp_joy_id;
int tmp_joy_flag = 0;
SDL_Haptic * rc_haptic[MAX_JOYSTICKS]; //1 for each joystick
double rc_pressure = 0;
int rc_touchX = 0;
int rc_touchY = 0;
int rc_motionX = 0;
int rc_motionY = 0;
int rc_touch = 0;
int rc_mt_status = 0;
int rc_mt_x = 0;
int rc_mt_y = 0;
int rc_mt_numFingers = 0;
double rc_mt_theta = 0;
double rc_mt_dist = 0;
SDL_TouchID rc_touchDevice;
SDL_Finger rc_finger[MAX_FINGERS];
set<int> rc_fingers_pressed;
SDL_Sensor * rc_accel[MAX_ACCELS];
int num_accels = 0;
SDL_Sensor * rc_gyro[MAX_GYROS];
int num_gyros = 0;
struct SDLKeyMap
{
SDLKeyMap() {}
SDLKeyMap(s32 x11, s32 win32)
: SDLKey(x11), Win32Key(win32)
{
}
s32 SDLKey;
s32 Win32Key;
bool operator<(const SDLKeyMap& o) const
{
return SDLKey<o.SDLKey;
}
};
core::array<SDLKeyMap> KeyMap;
void createKeyMap()
{
// I don't know if this is the best method to create
// the lookuptable, but I'll leave it like that until
// I find a better version.
KeyMap.reallocate(105);
// buttons missing
KeyMap.push_back(SDLKeyMap(SDLK_BACKSPACE, irr::EKEY_CODE::KEY_BACK));
KeyMap.push_back(SDLKeyMap(SDLK_TAB, irr::EKEY_CODE::KEY_TAB));
KeyMap.push_back(SDLKeyMap(SDLK_CLEAR, irr::EKEY_CODE::KEY_CLEAR));
KeyMap.push_back(SDLKeyMap(SDLK_RETURN, irr::EKEY_CODE::KEY_RETURN));
// combined modifiers missing
KeyMap.push_back(SDLKeyMap(SDLK_PAUSE, irr::EKEY_CODE::KEY_PAUSE));
KeyMap.push_back(SDLKeyMap(SDLK_CAPSLOCK, irr::EKEY_CODE::KEY_CAPITAL));
// asian letter keys missing
KeyMap.push_back(SDLKeyMap(SDLK_ESCAPE, irr::EKEY_CODE::KEY_ESCAPE));
// asian letter keys missing
KeyMap.push_back(SDLKeyMap(SDLK_SPACE, irr::EKEY_CODE::KEY_SPACE));
KeyMap.push_back(SDLKeyMap(SDLK_PAGEUP, irr::EKEY_CODE::KEY_PRIOR));
KeyMap.push_back(SDLKeyMap(SDLK_PAGEDOWN, irr::EKEY_CODE::KEY_NEXT));
KeyMap.push_back(SDLKeyMap(SDLK_END, irr::EKEY_CODE::KEY_END));
KeyMap.push_back(SDLKeyMap(SDLK_HOME, irr::EKEY_CODE::KEY_HOME));
KeyMap.push_back(SDLKeyMap(SDLK_LEFT, irr::EKEY_CODE::KEY_LEFT));
KeyMap.push_back(SDLKeyMap(SDLK_UP, irr::EKEY_CODE::KEY_UP));
KeyMap.push_back(SDLKeyMap(SDLK_RIGHT, irr::EKEY_CODE::KEY_RIGHT));
KeyMap.push_back(SDLKeyMap(SDLK_DOWN, irr::EKEY_CODE::KEY_DOWN));
// select missing
KeyMap.push_back(SDLKeyMap(SDLK_PRINTSCREEN, irr::EKEY_CODE::KEY_PRINT));
// execute missing
KeyMap.push_back(SDLKeyMap(SDLK_PRINTSCREEN, irr::EKEY_CODE::KEY_SNAPSHOT));
KeyMap.push_back(SDLKeyMap(SDLK_INSERT, irr::EKEY_CODE::KEY_INSERT));
KeyMap.push_back(SDLKeyMap(SDLK_DELETE, irr::EKEY_CODE::KEY_DELETE));
KeyMap.push_back(SDLKeyMap(SDLK_HELP, irr::EKEY_CODE::KEY_HELP));
KeyMap.push_back(SDLKeyMap(SDLK_0, irr::EKEY_CODE::KEY_KEY_0));
KeyMap.push_back(SDLKeyMap(SDLK_1, irr::EKEY_CODE::KEY_KEY_1));
KeyMap.push_back(SDLKeyMap(SDLK_2, irr::EKEY_CODE::KEY_KEY_2));
KeyMap.push_back(SDLKeyMap(SDLK_3, irr::EKEY_CODE::KEY_KEY_3));
KeyMap.push_back(SDLKeyMap(SDLK_4, irr::EKEY_CODE::KEY_KEY_4));
KeyMap.push_back(SDLKeyMap(SDLK_5, irr::EKEY_CODE::KEY_KEY_5));
KeyMap.push_back(SDLKeyMap(SDLK_6, irr::EKEY_CODE::KEY_KEY_6));
KeyMap.push_back(SDLKeyMap(SDLK_7, irr::EKEY_CODE::KEY_KEY_7));
KeyMap.push_back(SDLKeyMap(SDLK_8, irr::EKEY_CODE::KEY_KEY_8));
KeyMap.push_back(SDLKeyMap(SDLK_9, irr::EKEY_CODE::KEY_KEY_9));
KeyMap.push_back(SDLKeyMap(SDLK_a, irr::EKEY_CODE::KEY_KEY_A));
KeyMap.push_back(SDLKeyMap(SDLK_b, irr::EKEY_CODE::KEY_KEY_B));
KeyMap.push_back(SDLKeyMap(SDLK_c, irr::EKEY_CODE::KEY_KEY_C));
KeyMap.push_back(SDLKeyMap(SDLK_d, irr::EKEY_CODE::KEY_KEY_D));
KeyMap.push_back(SDLKeyMap(SDLK_e, irr::EKEY_CODE::KEY_KEY_E));
KeyMap.push_back(SDLKeyMap(SDLK_f, irr::EKEY_CODE::KEY_KEY_F));
KeyMap.push_back(SDLKeyMap(SDLK_g, irr::EKEY_CODE::KEY_KEY_G));
KeyMap.push_back(SDLKeyMap(SDLK_h, irr::EKEY_CODE::KEY_KEY_H));
KeyMap.push_back(SDLKeyMap(SDLK_i, irr::EKEY_CODE::KEY_KEY_I));
KeyMap.push_back(SDLKeyMap(SDLK_j, irr::EKEY_CODE::KEY_KEY_J));
KeyMap.push_back(SDLKeyMap(SDLK_k, irr::EKEY_CODE::KEY_KEY_K));
KeyMap.push_back(SDLKeyMap(SDLK_l, irr::EKEY_CODE::KEY_KEY_L));
KeyMap.push_back(SDLKeyMap(SDLK_m, irr::EKEY_CODE::KEY_KEY_M));
KeyMap.push_back(SDLKeyMap(SDLK_n, irr::EKEY_CODE::KEY_KEY_N));
KeyMap.push_back(SDLKeyMap(SDLK_o, irr::EKEY_CODE::KEY_KEY_O));
KeyMap.push_back(SDLKeyMap(SDLK_p, irr::EKEY_CODE::KEY_KEY_P));
KeyMap.push_back(SDLKeyMap(SDLK_q, irr::EKEY_CODE::KEY_KEY_Q));
KeyMap.push_back(SDLKeyMap(SDLK_r, irr::EKEY_CODE::KEY_KEY_R));
KeyMap.push_back(SDLKeyMap(SDLK_s, irr::EKEY_CODE::KEY_KEY_S));
KeyMap.push_back(SDLKeyMap(SDLK_t, irr::EKEY_CODE::KEY_KEY_T));
KeyMap.push_back(SDLKeyMap(SDLK_u, irr::EKEY_CODE::KEY_KEY_U));
KeyMap.push_back(SDLKeyMap(SDLK_v, irr::EKEY_CODE::KEY_KEY_V));
KeyMap.push_back(SDLKeyMap(SDLK_w, irr::EKEY_CODE::KEY_KEY_W));
KeyMap.push_back(SDLKeyMap(SDLK_x, irr::EKEY_CODE::KEY_KEY_X));
KeyMap.push_back(SDLKeyMap(SDLK_y, irr::EKEY_CODE::KEY_KEY_Y));
KeyMap.push_back(SDLKeyMap(SDLK_z, irr::EKEY_CODE::KEY_KEY_Z));
// TODO:
//KeyMap.push_back(SDLKeyMap(SDLK_LSUPER, KEY_LWIN));
// TODO:
//KeyMap.push_back(SDLKeyMap(SDLK_RSUPER, KEY_RWIN));
// apps missing
KeyMap.push_back(SDLKeyMap(SDLK_POWER, irr::EKEY_CODE::KEY_SLEEP)); //??
KeyMap.push_back(SDLKeyMap(SDLK_KP_0, irr::EKEY_CODE::KEY_NUMPAD0));
KeyMap.push_back(SDLKeyMap(SDLK_KP_1, irr::EKEY_CODE::KEY_NUMPAD1));
KeyMap.push_back(SDLKeyMap(SDLK_KP_2, irr::EKEY_CODE::KEY_NUMPAD2));
KeyMap.push_back(SDLKeyMap(SDLK_KP_3, irr::EKEY_CODE::KEY_NUMPAD3));
KeyMap.push_back(SDLKeyMap(SDLK_KP_4, irr::EKEY_CODE::KEY_NUMPAD4));
KeyMap.push_back(SDLKeyMap(SDLK_KP_5, irr::EKEY_CODE::KEY_NUMPAD5));
KeyMap.push_back(SDLKeyMap(SDLK_KP_6, irr::EKEY_CODE::KEY_NUMPAD6));
KeyMap.push_back(SDLKeyMap(SDLK_KP_7, irr::EKEY_CODE::KEY_NUMPAD7));
KeyMap.push_back(SDLKeyMap(SDLK_KP_8, irr::EKEY_CODE::KEY_NUMPAD8));
KeyMap.push_back(SDLKeyMap(SDLK_KP_9, irr::EKEY_CODE::KEY_NUMPAD9));
KeyMap.push_back(SDLKeyMap(SDLK_KP_MULTIPLY, irr::EKEY_CODE::KEY_MULTIPLY));
KeyMap.push_back(SDLKeyMap(SDLK_KP_PLUS, irr::EKEY_CODE::KEY_ADD));
// KeyMap.push_back(SDLKeyMap(SDLK_KP_, KEY_SEPARATOR));
KeyMap.push_back(SDLKeyMap(SDLK_KP_MINUS, irr::EKEY_CODE::KEY_SUBTRACT));
KeyMap.push_back(SDLKeyMap(SDLK_KP_PERIOD, irr::EKEY_CODE::KEY_DECIMAL));
KeyMap.push_back(SDLKeyMap(SDLK_KP_DIVIDE, irr::EKEY_CODE::KEY_DIVIDE));
KeyMap.push_back(SDLKeyMap(SDLK_F1, irr::EKEY_CODE::KEY_F1));
KeyMap.push_back(SDLKeyMap(SDLK_F2, irr::EKEY_CODE::KEY_F2));
KeyMap.push_back(SDLKeyMap(SDLK_F3, irr::EKEY_CODE::KEY_F3));
KeyMap.push_back(SDLKeyMap(SDLK_F4, irr::EKEY_CODE::KEY_F4));
KeyMap.push_back(SDLKeyMap(SDLK_F5, irr::EKEY_CODE::KEY_F5));
KeyMap.push_back(SDLKeyMap(SDLK_F6, irr::EKEY_CODE::KEY_F6));
KeyMap.push_back(SDLKeyMap(SDLK_F7, irr::EKEY_CODE::KEY_F7));
KeyMap.push_back(SDLKeyMap(SDLK_F8, irr::EKEY_CODE::KEY_F8));
KeyMap.push_back(SDLKeyMap(SDLK_F9, irr::EKEY_CODE::KEY_F9));
KeyMap.push_back(SDLKeyMap(SDLK_F10, irr::EKEY_CODE::KEY_F10));
KeyMap.push_back(SDLKeyMap(SDLK_F11, irr::EKEY_CODE::KEY_F11));
KeyMap.push_back(SDLKeyMap(SDLK_F12, irr::EKEY_CODE::KEY_F12));
KeyMap.push_back(SDLKeyMap(SDLK_F13, irr::EKEY_CODE::KEY_F13));
KeyMap.push_back(SDLKeyMap(SDLK_F14, irr::EKEY_CODE::KEY_F14));
KeyMap.push_back(SDLKeyMap(SDLK_F15, irr::EKEY_CODE::KEY_F15));
// no higher F-keys
// TODO:
//KeyMap.push_back(SDLKeyMap(SDLK_NUMLOCK, KEY_NUMLOCK));
KeyMap.push_back(SDLKeyMap(SDLK_SCROLLLOCK, irr::EKEY_CODE::KEY_SCROLL));
KeyMap.push_back(SDLKeyMap(SDLK_LSHIFT, irr::EKEY_CODE::KEY_LSHIFT));
KeyMap.push_back(SDLKeyMap(SDLK_RSHIFT, irr::EKEY_CODE::KEY_RSHIFT));
KeyMap.push_back(SDLKeyMap(SDLK_LCTRL, irr::EKEY_CODE::KEY_LCONTROL));
KeyMap.push_back(SDLKeyMap(SDLK_RCTRL, irr::EKEY_CODE::KEY_RCONTROL));
KeyMap.push_back(SDLKeyMap(SDLK_LALT, irr::EKEY_CODE::KEY_LMENU));
KeyMap.push_back(SDLKeyMap(SDLK_RALT, irr::EKEY_CODE::KEY_RMENU));
KeyMap.push_back(SDLKeyMap(SDLK_PLUS, irr::EKEY_CODE::KEY_PLUS));
KeyMap.push_back(SDLKeyMap(SDLK_COMMA, irr::EKEY_CODE::KEY_COMMA));
KeyMap.push_back(SDLKeyMap(SDLK_MINUS, irr::EKEY_CODE::KEY_MINUS));
KeyMap.push_back(SDLKeyMap(SDLK_PERIOD, irr::EKEY_CODE::KEY_PERIOD));
// some special keys missing
KeyMap.sort();
}
IrrlichtDevice* device;
irr::video::IVideoDriver * VideoDriver;
irr::scene::ISceneManager *SceneManager;
SDL_Window* rc_window;
irr::core::dimension2d<u32> rc_window_size;
struct rc_scene_properties_obj
{
irr::scene::ISceneNode* sky = NULL;
};
rc_scene_properties_obj rc_scene_properties;
#define RC_CONSTRAINT_TYPE_POINT 1
#define RC_CONSTRAINT_TYPE_HINGE 2
#define RC_CONSTRAINT_TYPE_SLIDER 3
#define RC_CONSTRAINT_TYPE_CONE 4
struct rc_constraint_obj
{
btTypedConstraint* constraint;
int type;
};
struct rc_physicsWorld3D_obj
{
irrBulletWorld* world;
irr::f32 DeltaTime;
irr::u32 maxSubSteps;
irr::f32 fixedTimeStep;
irr::u32 TimeStamp;
irr::core::array<rc_constraint_obj> constraints;
};
rc_physicsWorld3D_obj rc_physics3D;
//Canvases
class rc_contactListener_obj : public b2ContactListener
{
void BeginContact(b2Contact* contact)
{
rc_sprite2D_obj* spriteA = (rc_sprite2D_obj*) contact->GetFixtureA()->GetBody()->GetUserData().pointer;
rc_sprite2D_obj* spriteB = (rc_sprite2D_obj*) contact->GetFixtureB()->GetBody()->GetUserData().pointer;
//std::cout << "sprite[" << spriteA->id << "] collide with sprite[" << spriteB->id << "]" << std::endl;
}
void EndContact(b2Contact* contact)
{
}
};
struct rc_physicsWorld2D_obj
{
bool enabled = false;
b2World* world;
rc_contactListener_obj* contact_listener;
float timeStep = 1/60.0; //the length of time passed to simulate (seconds)
int velocityIterations = 8; //how strongly to correct velocity
int positionIterations = 3; //how strongly to correct position
};
#define RC_CANVAS_TYPE_2D 0
#define RC_CANVAS_TYPE_3D 1
#define RC_CANVAS_TYPE_SPRITE 2
#define RC_PROJECTION_TYPE_ORTHOGRAPHIC 0
#define RC_PROJECTION_TYPE_PERSPECTIVE 1
struct rc_canvas_obj
{
irr::video::ITexture* texture;
//irr::video::ITexture* sprite_layer;
int type;
irr::core::dimension2d<u32> dimension;
struct rc_canvas_viewport
{
irr::core::vector2d<s32> position;
irr::core::dimension2d<u32> dimension;
} viewport;
bool show3D = false;
Camera camera;
irr::core::vector2d<s32> offset;
int mode;
bool visible = true;
int z = 0;
irr::u32 color_mod;
rc_physicsWorld2D_obj physics2D;
irr::core::array<rc_sprite2D_obj*> sprite;
};
irr::core::array<rc_canvas_obj> rc_canvas;
irr::core::array<u32> rc_canvas_zOrder;
int rc_active_canvas = -1;
bool hasPreUpdated = false;
irr::video::SColor rc_active_color(0,0,0,0);
irr::video::SColor rc_clear_color(0,0,0,0);
bool rc_init_events = false;
bool rc_init_timer = false;
bool rc_init_video = false;
bool rc_init_joystick = false;
bool rc_init_haptic = false;
bool rc_init_sensor = false;
bool rc_init_noparachute = false;
bool rc_init_audio = false;
irr::s32 MouseX, MouseY, MouseXRel, MouseYRel;
irr::u32 MouseButtonStates;
int rc_win_event = -1;
#define RC_WIN_EVENT_CLOSE 1
#define RC_WIN_EVENT_MINIMIZE 2
#define RC_WIN_EVENT_MAXIMIZE 3
#define RC_WIN_EVENT_RESIZE 4
bool rc_win_exitOnClose = true;
std::string rc_textinput_string = "";
std::string rc_textinput_char = "";
int rc_textinput_timer = 0;
int rc_textinput_delay = 100;
bool rc_textinput_flag = true;
bool rc_textinput_isActive = false;
int rc_textinput_waitHold = 800;
bool rc_textinput_hold = false;
bool rc_toggleBackspace = true;
static Uint32 baseticks = 0;
int rc_inkey_val = 0;
const Uint8 * keyState = NULL;
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
struct rc_font_obj
{
CGUITTFace* face;
CGUIFreetypeFont* font;
int font_size;
};
irr::core::array<rc_font_obj*> rc_font;
int rc_active_font = -1;
bool mobile_active_window_flag = true;
//------------ 3D Graphics ----------------//
#define RC_MESH_TYPE_NONE 0
#define RC_MESH_TYPE_ANIMATED 1
struct rc_mesh_obj
{
int mesh_type = 0;
irr::scene::IAnimatedMesh* mesh;
};
irr::core::array<rc_mesh_obj> rc_mesh;
struct rc_an8_obj
{
bool active;
an8::an8_project project;
};
irr::core::array<rc_an8_obj> rc_an8;
#define RC_NODE_TYPE_NONE 0
#define RC_NODE_TYPE_MESH 1
#define RC_NODE_TYPE_OTMESH 2
#define RC_NODE_TYPE_LIGHT 3
#define RC_NODE_TYPE_TERRAIN 4
#define RC_NODE_TYPE_WATER 5
#define RC_NODE_TYPE_BILLBOARD 6
#define RC_NODE_TYPE_PARTICLE 7
#define RC_NODE_SHAPE_TYPE_NONE 0
#define RC_NODE_SHAPE_TYPE_BOX 1
#define RC_NODE_SHAPE_TYPE_SPHERE 2
#define RC_NODE_SHAPE_TYPE_CYLINDER 3
#define RC_NODE_SHAPE_TYPE_CAPSULE 4
#define RC_NODE_SHAPE_TYPE_CONE 5
#define RC_NODE_SHAPE_TYPE_CONVEXHULL 6
#define RC_NODE_SHAPE_TYPE_TRIMESH 7
#define RC_NODE_SHAPE_TYPE_HEIGHTFIELD 8
struct rc_node_physics_collision
{
int actorA;
int actorB;
irr::core::array<irr::core::vector3df> pointA;
irr::core::array<irr::core::vector3df> pointB;
irr::core::array<irr::core::vector3df> normalB;
};
irr::core::array<rc_node_physics_collision> rc_collisions;
struct rc_node_physics
{
IRigidBody* rigid_body;
int shape_type;
bool isSolid;
double mass;
irr::core::vector3df gravity; //only used when changing from Solid to Non-Solid and vice versa
irr::core::array<irr::u32> collisions;
};
#define RC_PARTICLE_TYPE_POINT 1
#define RC_PARTICLE_TYPE_BOX 2
#define RC_PARTICLE_TYPE_SPHERE 3
#define RC_PARTICLE_TYPE_CYLINDER 4
#define RC_PARTICLE_TYPE_MESH 5
#define RC_PARTICLE_TYPE_RING 6
struct rc_particle_properties_obj
{
int particle_type = 0;
bool everyMeshVertex;
irr::s32 mbNumber = 0;
irr::f32 normalDirectionModifier;
bool useNormalDirection;
irr::s32 mesh_id;
irr::core::vector3df direction;
irr::u32 minParticlesPerSecond;
irr::u32 maxParticlesPerSecond;
irr::video::SColor minStartColor;
irr::video::SColor maxStartColor;
irr::u32 lifeTimeMin;
irr::u32 lifeTimeMax;
irr::s32 maxAngleDegrees;
irr::core::dimension2df minStartSize;
irr::core::dimension2df maxStartSize;
irr::core::vector3df center;
irr::f32 radius;
irr::f32 ringThickness;
irr::core::aabbox3df box;
irr::core::vector3df normal;
irr::f32 length;
bool outlineOnly;
};
#define RC_ANIMATION_MD2 -2
#define RC_ANIMATION_TRANSITION -3
struct rc_actor_animation_obj
{
bool active;
int start_frame;
int end_frame;
double fps;
irr::u32 frame_start_time;
irr::u32 frame_swap_time;
};
struct rc_scene_node
{
int node_type = 0;
irr::scene::ISceneNode* mesh_node;
irr::scene::IShadowVolumeSceneNode* shadow;
rc_node_physics physics;
bool transition;
double transition_frame;
double transition_time;
double transition_start_time;
rc_particle_properties_obj particle_properties;
int material_ref_index = -1;
int current_animation;
int num_animation_loops;
int current_animation_loop;
bool isPlaying;
irr::core::array<int> deleted_animation;
irr::core::array<rc_actor_animation_obj> animation;
};
irr::core::array<rc_scene_node> rc_actor;
irr::core::array<int> rc_transition_actor;
class rc_animEndCallBack : public IAnimationEndCallBack
{
public:
rc_scene_node* ref_actor;
void OnAnimationEnd( IAnimatedMeshSceneNode *node)
{
if(ref_actor->current_animation_loop < ref_actor->num_animation_loops || ref_actor->num_animation_loops < 0)
{
//std::cout << "animating" << std::endl;
irr::scene::IAnimatedMeshSceneNode* node = (irr::scene::IAnimatedMeshSceneNode*) ref_actor->mesh_node;
int animation = ref_actor->current_animation;
if(animation < 0 || animation >= ref_actor->animation.size())
return;
int start_frame = ref_actor->animation[animation].start_frame;
int end_frame = ref_actor->animation[animation].end_frame;
node->setFrameLoop(start_frame, end_frame);
ref_actor->current_animation_loop++;
}
else
{
ref_actor->isPlaying = false;
}
//std::cout << "The animation has ended!" << std::endl;
// Your callback code goes there.
}
};
void myTickCallback2(btSoftRigidDynamicsWorld* dynamicsWorld, btScalar timeStep)
{
rc_collisions.clear();
int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds();
int c_index = 0;
rc_node_physics_collision collision;
for(int i = 0; i < rc_actor.size(); i++)
{
rc_actor[i].physics.collisions.clear();
}
for (int i = 0; i < rc_physics3D.world->getNumManifolds(); i++)
{
ICollisionCallbackInformation* manifold = rc_physics3D.world->getCollisionCallback(i);
int numContacts = manifold->getPointer()->getNumContacts();
int actorA = manifold->getBody0()->getIdentification()->getId();
int actorB = manifold->getBody1()->getIdentification()->getId();
collision.actorA = actorA;
collision.actorB = actorB;
//std::cout << "Collision Details: " << actorA << ", " << actorB << ", " << numContacts << std::endl;
if(numContacts < 1)
continue;
for (int j = 0; j < numContacts; j++)
{
SManifoldPoint pt = manifold->getContactPoint(j);
collision.pointA.push_back(pt.getPositionWorldOnA());
collision.pointB.push_back(pt.getPositionWorldOnB());
collision.normalB.push_back(pt.getNormalWorldOnB());
}
c_index = rc_collisions.size();
rc_collisions.push_back(collision);
rc_actor[actorA].physics.collisions.push_back(c_index);
rc_actor[actorB].physics.collisions.push_back(c_index);
}
for(int i = 0; i < rc_actor.size(); i++)
{
if(!rc_actor[i].physics.isSolid)
{
if(rc_actor[i].physics.collisions.size() > 0)
{
rc_physics3D.world->removeCollisionObject(rc_actor[i].physics.rigid_body, false);
rc_physics3D.world->addRigidBody(rc_actor[i].physics.rigid_body);
rc_actor[i].physics.rigid_body->setMassProps(1, irr::core::vector3df(0,0,0));
rc_actor[i].physics.rigid_body->setGravity(irr::core::vector3df(0,0,0));
}
}
}
}
#define RC_ACTOR_TEXTURE_TYPE_IMAGE 0
#define RC_ACTOR_TEXTURE_TYPE_CANVAS 1
// Function to calculate a point on a cubic Bezier curve
vector3df bezierPoint(const vector3df& p0, const vector3df& p1, const vector3df& p2, const vector3df& p3, float t) {
float u = 1.0f - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
vector3df p = uuu * p0; // (1-t)^3 * p0
p += 3 * uu * t * p1; // 3 * (1-t)^2 * t * p1
p += 3 * u * tt * p2; // 3 * (1-t) * t^2 * p2
p += ttt * p3; // t^3 * p3
return p;
}
// Function to draw a Bezier curve
void drawBezierCurve(IVideoDriver* driver, const vector3df& p0, const vector3df& p1, const vector3df& p2, const vector3df& p3, SColor color, int segments) {
std::vector<vector3df> points;
for (int i = 0; i <= segments; ++i) {
float t = static_cast<float>(i) / segments;
points.push_back(bezierPoint(p0, p1, p2, p3, t));
}
for (size_t i = 0; i < points.size() - 1; ++i) {
driver->draw3DLine(points[i], points[i + 1], color);
}
}
void printIrrMatrix(irr::core::matrix4 m)
{
for(int i = 0; i < 4; i++)
std::cout << "[ " << m[i*4] << ", " << m[i*4+1] << ", " << m[i*4+2] << ", " << m[i*4+3] << " ]" << std::endl;
}
struct rc_image_obj
{
irr::video::ITexture* image;
Uint8 alpha = 255;
irr::video::SColor color_mod = irr::video::SColor(255,255,255,255);
};
irr::core::array<rc_image_obj> rc_image;
irr::video::E_BLEND_OPERATION rc_blend_mode = irr::video::EBO_ADD;
bool rc_bilinear_filter = false;
void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect<irr::s32> sourceRect, irr::core::position2d<irr::s32> position, irr::core::position2d<irr::s32> rotationPoint, irr::f32 rotation, irr::core::vector2df scale, bool useAlphaChannel, irr::video::SColor color, irr::core::vector2d<irr::f32> screenSize)
{
if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size())
return;
// Store and clear the projection matrix
irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION);
driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4());
// Store and clear the view matrix
irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW);
driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4());
// Store and clear the world matrix
irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD);
driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4());
// Find horizontal and vertical axes after rotation
irr::f32 c = cos(-rotation*irr::core::DEGTORAD);
irr::f32 s = sin(-rotation*irr::core::DEGTORAD);
irr::core::vector2df horizontalAxis(c,s);
irr::core::vector2df verticalAxis(s,-c);
// First, we'll find the offset of the center and then where the center would be after rotation
irr::core::vector2df centerOffset(position.X+sourceRect.getWidth()/2.0f*scale.X-rotationPoint.X,position.Y+sourceRect.getHeight()/2.0f*scale.Y-rotationPoint.Y);
irr::core::vector2df center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis;
center.X += rotationPoint.X;
center.Y += rotationPoint.Y;
// Now find the corners based off the center
irr::core::vector2df cornerOffset(sourceRect.getWidth()*scale.X/2.0f,sourceRect.getHeight()*scale.Y/2.0f);
verticalAxis *= cornerOffset.Y;
horizontalAxis *= cornerOffset.X;
irr::core::vector2df corner[4];
corner[0] = center + verticalAxis - horizontalAxis;
corner[1] = center + verticalAxis + horizontalAxis;
corner[2] = center - verticalAxis - horizontalAxis;
corner[3] = center - verticalAxis + horizontalAxis;
// Find the uv coordinates of the sourceRect
irr::core::vector2df textureSize(texture->getSize().Width, texture->getSize().Height);
irr::core::vector2df uvCorner[4];
uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y);
uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y);
uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y);
uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.LowerRightCorner.Y);
for (irr::s32 i = 0; i < 4; i++)
uvCorner[i] /= textureSize;
// Vertices for the image
irr::video::S3DVertex vertices[4];
irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 };
// Convert pixels to world coordinates
//irr::core::vector2df screenSize(rc_canvas[rc_active_canvas].dimension.Width, rc_canvas[rc_active_canvas].dimension.Height);
for (irr::s32 i = 0; i < 4; i++) {
vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1);
vertices[i].TCoords = uvCorner[i];
vertices[i].Color = color;
}
// Create the material
// IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE:
// material.BlendOperation = irr::video::EBO_ADD;
irr::video::SMaterial material;
material.Lighting = false;
material.ZWriteEnable = irr::video::EZW_OFF;
material.ZBuffer = false;
material.BackfaceCulling = false;
material.TextureLayer[0].Texture = texture;
material.TextureLayer[0].BilinearFilter = rc_bilinear_filter;
material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR);
material.BlendOperation = rc_blend_mode;
//material.BlendOperation = irr::video::EBO_ADD;
if (useAlphaChannel)
material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND;
else
material.MaterialType = irr::video::EMT_SOLID;
driver->setMaterial(material);
driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2);
// Restore projection, world, and view matrices
driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat);
driver->setTransform(irr::video::ETS_VIEW,oldViewMat);
driver->setTransform(irr::video::ETS_WORLD,oldWorldMat);
}
void draw2DImage2(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect<irr::s32> sourceRect, irr::core::rect<irr::s32> destRect, irr::core::position2d<irr::s32> rotationPoint, irr::f32 rotation, bool useAlphaChannel, irr::video::SColor color, irr::core::vector2d<irr::f32> screenSize )
{
if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size())
return;
// Store and clear the projection matrix
irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION);
driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4());
// Store and clear the view matrix
irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW);
driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4());
// Store and clear the world matrix
irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD);
driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4());
// Find horizontal and vertical axes after rotation
irr::f32 c = cos(-rotation*irr::core::DEGTORAD);
irr::f32 s = sin(-rotation*irr::core::DEGTORAD);
irr::core::vector2df horizontalAxis(c,s);
irr::core::vector2df verticalAxis(s,-c);
// First, we'll find the offset of the center and then where the center would be after rotation
irr::core::vector2df centerOffset(destRect.UpperLeftCorner.X+destRect.getWidth()/2.0f-rotationPoint.X,destRect.UpperLeftCorner.Y+destRect.getHeight()/2.0f-rotationPoint.Y);
irr::core::vector2df center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis;
center.X += rotationPoint.X;
center.Y += rotationPoint.Y;
// Now find the corners based off the center
irr::core::vector2df cornerOffset(destRect.getWidth()/2.0f,destRect.getHeight()/2.0f);
verticalAxis *= cornerOffset.Y;
horizontalAxis *= cornerOffset.X;
irr::core::vector2df corner[4];
corner[0] = center + verticalAxis - horizontalAxis;
corner[1] = center + verticalAxis + horizontalAxis;
corner[2] = center - verticalAxis - horizontalAxis;
corner[3] = center - verticalAxis + horizontalAxis;
// Find the uv coordinates of the sourceRect
irr::core::vector2df textureSize(texture->getSize().Width, texture->getSize().Height);
irr::core::vector2df uvCorner[4];
uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y);
uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y);
uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y);
uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.LowerRightCorner.Y);
for (irr::s32 i = 0; i < 4; i++)
uvCorner[i] /= textureSize;
// Vertices for the image
irr::video::S3DVertex vertices[4];
irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 };
// Convert pixels to world coordinates
//irr::core::vector2df screenSize(rc_canvas[rc_active_canvas].dimension.Width, rc_canvas[rc_active_canvas].dimension.Height);
for (irr::s32 i = 0; i < 4; i++) {
vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1);
vertices[i].TCoords = uvCorner[i];
vertices[i].Color = color;
}
// Create the material
// IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE:
// material.BlendOperation = irr::video::EBO_ADD;
irr::video::SMaterial material;
material.Lighting = false;
material.ZWriteEnable = irr::video::EZW_OFF;
material.ZBuffer = false;
material.BackfaceCulling = false;
material.TextureLayer[0].Texture = texture;
material.TextureLayer[0].BilinearFilter = rc_bilinear_filter; //TODO: Add option to switch this on/off
material.BlendOperation = rc_blend_mode;
material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR);
//material.AntiAliasing = irr::video::EAAM_OFF;
if (useAlphaChannel)
material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND;
else
material.MaterialType = irr::video::EMT_SOLID;
driver->setMaterial(material);
driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2);
// Restore projection, world, and view matrices
driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat);
driver->setTransform(irr::video::ETS_VIEW,oldViewMat);
driver->setTransform(irr::video::ETS_WORLD,oldWorldMat);
}
#endif // RC_GFX_CORE_H_INCLUDED