Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,478 @@
|
||||
#include "scripts/binds.h"
|
||||
#include "obj/lock.h"
|
||||
#include "obj/object.h"
|
||||
#include "obj/universe.h"
|
||||
#include "obj/obj_group.h"
|
||||
#include "empire.h"
|
||||
#include "main/references.h"
|
||||
#include "render/render_state.h"
|
||||
#include "render/render_mesh.h"
|
||||
#include "render/lighting.h"
|
||||
#include "scene/mesh_node.h"
|
||||
#include "scene/mesh_icon_node.h"
|
||||
#include "scene/icon_node.h"
|
||||
#include "scene/animation/anim_node_sync.h"
|
||||
#include "scene/animation/anim_group.h"
|
||||
#include "scene/scripted_node.h"
|
||||
#include "scene/culling_node.h"
|
||||
#include "util/random.h"
|
||||
#include "vec2.h"
|
||||
#include "color.h"
|
||||
#include "processing.h"
|
||||
#include "physics/physics_world.h"
|
||||
|
||||
namespace scripts {
|
||||
|
||||
struct ObjectDesc {
|
||||
int type;
|
||||
unsigned flags;
|
||||
std::string name;
|
||||
double radius;
|
||||
vec3d position;
|
||||
Empire* owner;
|
||||
bool delayedCreation;
|
||||
|
||||
ObjectDesc() : type(0), flags(objValid | objUninitialized),
|
||||
radius(1.0), owner(0), delayedCreation(false) {
|
||||
}
|
||||
|
||||
void reset() {
|
||||
type = 0;
|
||||
flags = objValid | objUninitialized;
|
||||
radius = 1.0;
|
||||
owner = 0;
|
||||
delayedCreation = false;
|
||||
name.clear();
|
||||
position = vec3d();
|
||||
}
|
||||
};
|
||||
|
||||
void createDesc(void* mem) {
|
||||
new(mem) ObjectDesc();
|
||||
}
|
||||
|
||||
bool hintLocks = false;
|
||||
LockGroup* hintedGroup = 0;
|
||||
unsigned hintID = 0;
|
||||
|
||||
Object* makeObject(ObjectDesc& desc) {
|
||||
ScriptObjectType* stype = getScriptObjectType(desc.type);
|
||||
if(stype == 0) {
|
||||
throwException("Invalid object type to create.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LockGroup* group = 0;
|
||||
if(hintLocks)
|
||||
group = hintedGroup;
|
||||
else if(LockGroup* active = getActiveLockGroup())
|
||||
group = active;
|
||||
|
||||
Object* obj = Object::create(stype, group);
|
||||
obj->flags = desc.flags;
|
||||
obj->name = desc.name;
|
||||
obj->radius = desc.radius;
|
||||
obj->position = desc.position;
|
||||
if(desc.owner)
|
||||
obj->owner = desc.owner;
|
||||
else
|
||||
obj->owner = Empire::getDefaultEmpire();
|
||||
|
||||
if(!obj->getFlag(objNoPhysics))
|
||||
obj->physItem = devices.physics->registerItem(AABBoxd::fromCircle(obj->position, obj->radius), obj);
|
||||
|
||||
if(desc.delayedCreation)
|
||||
obj->setFlag(objStopTicking, true);
|
||||
|
||||
obj->owner->registerObject(obj);
|
||||
devices.universe->addChild(obj);
|
||||
obj->init();
|
||||
|
||||
if(hintLocks) {
|
||||
if(!group) {
|
||||
hintedGroup = obj->lockGroup;
|
||||
hintID = randomi(1,INT_MAX);
|
||||
obj->lockHint = hintID;
|
||||
}
|
||||
else {
|
||||
obj->lockHint = hintID;
|
||||
}
|
||||
}
|
||||
|
||||
obj->grab();
|
||||
if(!desc.delayedCreation)
|
||||
obj->postInit();
|
||||
return obj;
|
||||
}
|
||||
|
||||
ObjectGroup* makeGroup(ObjectDesc& desc, unsigned count) {
|
||||
ScriptObjectType* stype = getScriptObjectType(desc.type);
|
||||
if(stype == 0) {
|
||||
throwException("Invalid object type to create.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LockGroup* lockGroup = 0;
|
||||
if(hintLocks)
|
||||
lockGroup = hintedGroup;
|
||||
|
||||
ObjectGroup* group = new ObjectGroup(count);
|
||||
group->grab();
|
||||
|
||||
for(unsigned i = 0; i < count; ++i) {
|
||||
Object* obj = Object::create(stype, lockGroup);
|
||||
if(hintLocks)
|
||||
obj->lockHint = hintID;
|
||||
lockGroup = obj->lockGroup;
|
||||
|
||||
obj->name = desc.name;
|
||||
obj->radius = desc.radius;
|
||||
obj->position = desc.position;
|
||||
if(desc.owner)
|
||||
obj->owner = desc.owner;
|
||||
else
|
||||
obj->owner = Empire::getDefaultEmpire();
|
||||
|
||||
if(desc.delayedCreation)
|
||||
obj->setFlag(objStopTicking, true);
|
||||
|
||||
obj->group = group;
|
||||
group->grab();
|
||||
|
||||
if(!obj->getFlag(objNoPhysics)) {
|
||||
obj->physItem = group->getPhysicsItem(i);
|
||||
obj->physItem->bound = AABBoxd::fromCircle(obj->position, obj->radius);
|
||||
obj->physItem->gridLocation = 0;
|
||||
obj->physItem->type = PIT_Object;
|
||||
obj->physItem->object = obj;
|
||||
|
||||
obj->grab();
|
||||
}
|
||||
|
||||
group->setObject(i, obj);
|
||||
}
|
||||
|
||||
group->postInit();
|
||||
|
||||
for(unsigned i = 0; i < count; ++i) {
|
||||
Object* obj = group->getObject(i);
|
||||
|
||||
obj->owner->registerObject(obj);
|
||||
devices.universe->addChild(obj);
|
||||
obj->init();
|
||||
|
||||
if(!desc.delayedCreation)
|
||||
obj->postInit();
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
struct LightDesc {
|
||||
Colorf diffuse;
|
||||
Colorf specular;
|
||||
float att_quadratic;
|
||||
vec3f position;
|
||||
float radius;
|
||||
|
||||
LightDesc() : att_quadratic(0.f) {
|
||||
}
|
||||
};
|
||||
|
||||
void createLight(void* mem) {
|
||||
new(mem) LightDesc();
|
||||
}
|
||||
|
||||
void makeLight(LightDesc& desc) {
|
||||
auto* light = new render::light::PointLight();
|
||||
|
||||
light->diffuse = desc.diffuse;
|
||||
light->specular = desc.specular;
|
||||
light->att_quadratic = desc.att_quadratic;
|
||||
light->position = desc.position;
|
||||
light->radius = desc.radius;
|
||||
|
||||
render::light::registerLight(light);
|
||||
}
|
||||
|
||||
void makeNodeLight(LightDesc& desc, scene::Node* follow) {
|
||||
auto* light = new render::light::NodePointLight(follow); //grabbed by constructor
|
||||
|
||||
light->diffuse = desc.diffuse;
|
||||
light->specular = desc.specular;
|
||||
light->att_quadratic = desc.att_quadratic;
|
||||
light->position = desc.position;
|
||||
light->radius = desc.radius;
|
||||
|
||||
render::light::registerLight(light);
|
||||
}
|
||||
|
||||
struct MeshDesc {
|
||||
const render::RenderState* material;
|
||||
const render::RenderMesh* mesh;
|
||||
const render::SpriteSheet* iconSheet;
|
||||
unsigned iconIndex;
|
||||
bool memorable;
|
||||
|
||||
Colorf color;
|
||||
|
||||
MeshDesc() : material(0), mesh(0), iconSheet(0), iconIndex(0), memorable(false) {
|
||||
}
|
||||
};
|
||||
|
||||
void createMeshDesc(void* mem) {
|
||||
new(mem) MeshDesc();
|
||||
}
|
||||
|
||||
void bindMesh(Object* obj, MeshDesc& desc) {
|
||||
if(obj->node) {
|
||||
throwException("Binding mesh to object that already has a node.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!desc.material || !desc.mesh) {
|
||||
throwException("Mesh descriptor data incomplete (missing material/model?).");
|
||||
return;
|
||||
}
|
||||
|
||||
scene::Node* mesh;
|
||||
if(!desc.iconSheet)
|
||||
mesh = new scene::MeshNode(desc.mesh, desc.material);
|
||||
else
|
||||
mesh = new scene::MeshIconNode(desc.mesh, desc.material,
|
||||
desc.iconSheet, desc.iconIndex);
|
||||
mesh->position = mesh->abs_position = obj->position;
|
||||
mesh->scale = mesh->abs_scale = obj->radius;
|
||||
mesh->color = desc.color;
|
||||
mesh->setObject(obj);
|
||||
mesh->animator = scene::NodeSyncAnimator::getSingleton();
|
||||
mesh->createPhysics();
|
||||
mesh->setFlag(scene::NF_Memorable, desc.memorable);
|
||||
|
||||
auto* player = Empire::getPlayerEmpire();
|
||||
if(player)
|
||||
mesh->visible = obj->isVisibleTo(player);
|
||||
|
||||
obj->node = mesh;
|
||||
|
||||
mesh->queueReparent(devices.scene);
|
||||
}
|
||||
|
||||
void bindGroupIcon(ObjectGroup* group, const render::SpriteSheet* sheet, unsigned spriteIndex) {
|
||||
scene::Node* icon = new scene::IconNode(sheet, spriteIndex);
|
||||
|
||||
icon->position = group->getCenter();
|
||||
double radius = group->getOwner()->radius;
|
||||
icon->scale = 0.3 * (1.0 + radius) / (3.0 + radius);
|
||||
|
||||
icon->animator = new scene::GroupAnim(group);
|
||||
|
||||
icon->queueReparent(devices.scene);
|
||||
}
|
||||
|
||||
scene::Node* bindCullingNode(Object* obj, const vec3d& pos, double radius) {
|
||||
if(obj->node) {
|
||||
throwException("Binding culling node to object that already has a node.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scene::Node* node = new scene::CullingNode(pos, radius);
|
||||
node->grab();
|
||||
|
||||
node->setObject(obj);
|
||||
obj->node = node;
|
||||
|
||||
node->queueReparent(devices.scene);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
scene::Node* createCullingNode(const vec3d& pos, double radius) {
|
||||
scene::Node* node = new scene::CullingNode(pos, radius);
|
||||
node->grab();
|
||||
|
||||
node->queueReparent(devices.scene);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
scene::Node* bindNode(Object* obj, const std::string& typeName) {
|
||||
scene::Node* node = scene::ScriptedNode::create(typeName);
|
||||
if(node) {
|
||||
node->grab();
|
||||
node->position = obj->position;
|
||||
node->scale = obj->radius;
|
||||
node->setObject(obj);
|
||||
node->animator = scene::NodeSyncAnimator::getSingleton();
|
||||
node->createPhysics();
|
||||
|
||||
auto* player = Empire::getPlayerEmpire();
|
||||
if(player)
|
||||
node->visible = obj->isVisibleTo(player);
|
||||
|
||||
obj->node = node;
|
||||
|
||||
node->queueReparent(devices.scene);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
scene::Node* makeNode(const std::string& typeName) {
|
||||
scene::Node* node = scene::ScriptedNode::create(typeName);
|
||||
if(node)
|
||||
node->queueReparent(devices.scene);
|
||||
return node;
|
||||
}
|
||||
|
||||
bool* startLockHint() {
|
||||
hintLocks = true;
|
||||
return &hintLocks;
|
||||
}
|
||||
|
||||
bool* objLockHint(Object* obj) {
|
||||
hintLocks = true;
|
||||
hintedGroup = obj->lockGroup;
|
||||
if(obj->lockHint)
|
||||
hintID = obj->lockHint;
|
||||
else
|
||||
hintID = randomi(1,INT_MAX);
|
||||
return &hintLocks;
|
||||
}
|
||||
|
||||
void endLockHint(bool* mem) {
|
||||
hintLocks = false;
|
||||
hintedGroup = 0;
|
||||
}
|
||||
|
||||
void RegisterObjectCreation(bool declarations) {
|
||||
if(declarations) {
|
||||
ClassBind desc("ObjectDesc", asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_C, sizeof(ObjectDesc));
|
||||
ClassBind mdesc("MeshDesc", asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_C, sizeof(MeshDesc));
|
||||
ClassBind ldesc("LightDesc", asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_C, sizeof(LightDesc));
|
||||
ClassBind lhint("LockHint", asOBJ_REF | asOBJ_SCOPED, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
ClassBind desc("ObjectDesc");
|
||||
classdoc(desc, "Descriptor for data to create objects.");
|
||||
|
||||
ClassBind mdesc("MeshDesc");
|
||||
classdoc(mdesc, "Descriptor to create a mesh representation for an object.");
|
||||
|
||||
ClassBind ldesc("LightDesc");
|
||||
classdoc(ldesc, "Descriptor to create a 3d light instance.");
|
||||
|
||||
ClassBind lhint("LockHint");
|
||||
classdoc(lhint, "Scoped structure. Any objects created within the same lock hint will"
|
||||
" start in the same lock group, reducing initial variability.");
|
||||
|
||||
//Objects
|
||||
desc.addMember("ObjectType type", offsetof(ObjectDesc, type))
|
||||
doc("Type of the object to create.");
|
||||
|
||||
desc.addMember("uint flags", offsetof(ObjectDesc, flags))
|
||||
doc("Flags the object starts with.");
|
||||
|
||||
desc.addMember("string name", offsetof(ObjectDesc, name))
|
||||
doc("Name the object is given.");
|
||||
|
||||
desc.addMember("bool delayedCreation", offsetof(ObjectDesc, delayedCreation))
|
||||
doc("If true, delay finalizing the creation until the script can do"
|
||||
" some of its own initialization steps. Don't forget to call"
|
||||
" finalizeCreation() on the object afterwards.");
|
||||
|
||||
desc.addMember("double radius", offsetof(ObjectDesc, radius))
|
||||
doc("Size of the object's bounding sphere.");
|
||||
|
||||
desc.addMember("vec3d position", offsetof(ObjectDesc, position))
|
||||
doc("Position the object is spawned at.");
|
||||
|
||||
desc.addMember("Empire@ owner", offsetof(ObjectDesc, owner))
|
||||
doc("Initial owner of the object.");
|
||||
|
||||
desc.addMethod("void reset()", asMETHOD(ObjectDesc, reset))
|
||||
doc("Reset the descriptor to its initial empty state.");
|
||||
desc.addConstructor("void f()", asFUNCTION(createDesc));
|
||||
|
||||
bind("Object@ makeObject(const ObjectDesc& desc)", asFUNCTION(makeObject))
|
||||
doc("Create an object based on a description of it.",
|
||||
"Object descriptor to use.", "Created object.");
|
||||
|
||||
bind("ObjectGroup@ makeObjectGroup(ObjectDesc& desc, uint count)", asFUNCTION(makeGroup))
|
||||
doc("Create an object group based on a description of an object.",
|
||||
"Object descriptor to use.", "Number of objects to create in the group.", "Created object.");
|
||||
|
||||
//Meshes
|
||||
mdesc.addMember("const Material@ material", offsetof(MeshDesc, material))
|
||||
doc("Texture to render on the model.");
|
||||
|
||||
mdesc.addMember("const Model@ model", offsetof(MeshDesc, mesh))
|
||||
doc("Model to use to display the object.");
|
||||
|
||||
mdesc.addMember("const SpriteSheet@ iconSheet", offsetof(MeshDesc, iconSheet))
|
||||
doc("Spritesheet to render distant icon from, if given.");
|
||||
|
||||
mdesc.addMember("uint iconIndex", offsetof(MeshDesc, iconIndex))
|
||||
doc("Icon in the spritesheet to use as a distant icon.");
|
||||
|
||||
mdesc.addMember("Colorf color", offsetof(MeshDesc, color))
|
||||
doc("Base color to set for the graphics node.");
|
||||
|
||||
mdesc.addMember("bool memorable", offsetof(MeshDesc, memorable))
|
||||
doc("Whether the node represents a memorable object.");
|
||||
|
||||
mdesc.addConstructor("void f()", asFUNCTION(createMeshDesc));
|
||||
|
||||
bind("void bindMesh(Object& obj, MeshDesc& desc)", asFUNCTION(bindMesh))
|
||||
doc("Bind a graphical representation to an object in accordance to a mesh descriptor.",
|
||||
"Game object to bind to.", "Descriptor for the mesh to display.");
|
||||
|
||||
bind("void bindGroupIcon(ObjectGroup& group, const SpriteSheet@ sheet, uint index)", asFUNCTION(bindGroupIcon))
|
||||
doc("Binds an icon to represent a ship group.", "", "", "");
|
||||
|
||||
bind("Node@ bindCullingNode(Object& obj, const vec3d&in position, double radius)", asFUNCTION(bindCullingNode))
|
||||
doc("Bind a node that can be used for region culling to the object.", "Object to bind to.",
|
||||
"Center position for the cullable region.", "Radius of the cullable region.", "Handle to the created node.");
|
||||
|
||||
bind("Node@ createCullingNode(const vec3d&in position, double radius)", asFUNCTION(createCullingNode))
|
||||
doc("Create a node that can be used for region culling.",
|
||||
"Center position for the cullable region.", "Radius of the cullable region.",
|
||||
"Handle to the created node.");
|
||||
|
||||
bind("Node@ bindNode(Object& obj, const string &in type)", asFUNCTION(bindNode))
|
||||
doc("Bind a custom graphical node to an object.", "Object to bind to.", "Type of script node to create.", "Handle to the created node.");
|
||||
|
||||
bind("Node@ createNode(const string &in type)", asFUNCTION(makeNode));
|
||||
|
||||
//Lights
|
||||
ldesc.addMember("Colorf diffuse", offsetof(LightDesc, diffuse))
|
||||
doc("Diffuse light color.");
|
||||
|
||||
ldesc.addMember("Colorf specular", offsetof(LightDesc, specular))
|
||||
doc("Specular light color.");
|
||||
|
||||
ldesc.addMember("float att_quadratic", offsetof(LightDesc, att_quadratic))
|
||||
doc("Quadratic attenuation.");
|
||||
|
||||
ldesc.addMember("float radius", offsetof(LightDesc, radius))
|
||||
doc("Radius associated with the light.");
|
||||
|
||||
ldesc.addMember("vec3f position", offsetof(LightDesc, position))
|
||||
doc("Position of the light in 3d space.");
|
||||
|
||||
ldesc.addConstructor("void f()", asFUNCTION(createLight));
|
||||
|
||||
bind("void makeLight(LightDesc& desc)", asFUNCTION(makeLight))
|
||||
doc("Create a light based on a description of it.",
|
||||
"Light descriptor to use.");
|
||||
bind("void makeLight(LightDesc& desc, Node& node)", asFUNCTION(makeNodeLight))
|
||||
doc("Create a light following a particular scene node.",
|
||||
"Light descriptor to use.", "Node to follow with the light.");
|
||||
|
||||
//Locking hints
|
||||
lhint.addFactory("LockHint@ f()", asFUNCTION(startLockHint));
|
||||
lhint.addFactory("LockHint@ f(Object& obj)", asFUNCTION(objLockHint));
|
||||
lhint.addExternBehaviour(asBEHAVE_RELEASE, "void f()", asFUNCTION(endLockHint));
|
||||
}
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user