Skip to content

Commit

Permalink
Implement most direct display commands
Browse files Browse the repository at this point in the history
  • Loading branch information
ligfx committed May 12, 2021
1 parent 8ed485e commit b481012
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 67 deletions.
8 changes: 8 additions & 0 deletions src/Agent.h
Expand Up @@ -218,6 +218,14 @@ class Agent : public std::enable_shared_from_this<Agent> {
int thrt = 0;
int size = 0;

// drawing
uint8_t alpha = 255;
bool draw_mirrored = false;
float scle = 1.0; // Sea-Monkeys only
bool strc = false; // Sea-Monkeys only
unsigned int strc_width; // Sea-Monkeys only
unsigned int strc_height; // Sea-Monkeys only

Agent(unsigned char f, unsigned char g, unsigned short s, unsigned int p);
virtual ~Agent();

Expand Down
16 changes: 14 additions & 2 deletions src/Backend.h
Expand Up @@ -32,10 +32,22 @@ using std::shared_ptr;

class creaturesImage;

struct RenderOptions {
uint8_t alpha = 255;
bool mirror = false;
float scale = 1.0;
bool override_drawsize = false;
int overridden_drawwidth;
int overridden_drawheight;
};

class RenderTarget {
public:
virtual void renderCreaturesImage(creaturesImage& tex, unsigned int frame, int x, int y, uint8_t transparency = 0, bool mirror = false) = 0;
virtual void renderCreaturesImage(const std::shared_ptr<creaturesImage>& tex, unsigned int frame, int x, int y, uint8_t transparency = 0, bool mirror = false) = 0;
virtual void renderCreaturesImage(creaturesImage& tex, unsigned int frame, int x, int y, RenderOptions options = {}) = 0;
void renderCreaturesImage(const std::shared_ptr<creaturesImage>& tex, unsigned int frame, int x, int y, RenderOptions options = {}) {
assert(tex.get() != nullptr);
renderCreaturesImage(*tex.get(), frame, x, y, options);
}
virtual void renderLine(int x1, int y1, int x2, int y2, unsigned int colour) = 0;
virtual void blitRenderTarget(RenderTarget* src, int x, int y, int w, int h) = 0;
virtual unsigned int getWidth() const = 0;
Expand Down
2 changes: 0 additions & 2 deletions src/CompoundPart.cpp
Expand Up @@ -86,8 +86,6 @@ CompoundPart::CompoundPart(Agent* p, unsigned int _id, int _x, int _y, int _z)
addZOrder();
x = _x;
y = _y;

has_alpha = false;
}

CompoundPart::~CompoundPart() {
Expand Down
3 changes: 0 additions & 3 deletions src/CompoundPart.h
Expand Up @@ -42,9 +42,6 @@ class CompoundPart : public renderable {
unsigned int zorder, id;
unsigned int part_sequence_number;

bool has_alpha;
unsigned char alpha;

virtual void render(class RenderTarget* renderer, int xoffset, int yoffset);
virtual void partRender(class RenderTarget* renderer, int xoffset, int yoffset) = 0;
virtual void tick() {}
Expand Down
12 changes: 10 additions & 2 deletions src/SpritePart.cpp
Expand Up @@ -22,7 +22,6 @@ SpritePart::SpritePart(Agent* p, unsigned int _id, std::string spritefile, unsig
is_transparent = (engine.version > 2);
framerate = 1;
framedelay = 0;
draw_mirrored = false;

if (sprite->numframes() <= firstimg) {
if (engine.gametype == "cv") {
Expand Down Expand Up @@ -54,7 +53,16 @@ void SpritePart::partRender(RenderTarget* renderer, int xoffset, int yoffset) {
}
}
assert(getCurrentSprite() < getSprite()->numframes());
renderer->renderCreaturesImage(getSprite(), getCurrentSprite(), xoffset + x, yoffset + y, has_alpha ? alpha : 0, draw_mirrored);
RenderOptions render_opts;
render_opts.alpha = parent->alpha;
render_opts.mirror = parent->draw_mirrored;
render_opts.scale = parent->scle;
if (parent->strc) {
render_opts.override_drawsize = true;
render_opts.overridden_drawwidth = parent->strc_width;
render_opts.overridden_drawheight = parent->strc_height;
}
renderer->renderCreaturesImage(getSprite(), getCurrentSprite(), xoffset + x, yoffset + y, render_opts);
}

void SpritePart::setFrameNo(unsigned int f) {
Expand Down
1 change: 0 additions & 1 deletion src/SpritePart.h
Expand Up @@ -11,7 +11,6 @@ class SpritePart : public AnimatablePart {

public:
bool is_transparent;
bool draw_mirrored;
unsigned char framerate;
unsigned int framedelay;
std::shared_ptr<creaturesImage> getSprite() { return sprite; }
Expand Down
4 changes: 3 additions & 1 deletion src/TextEntryPart.cpp
Expand Up @@ -98,7 +98,9 @@ void TextEntryPart::partRender(RenderTarget* renderer, int xoffset, int yoffset)

void TextEntryPart::renderCaret(RenderTarget* renderer, int xoffset, int yoffset) {
// TODO: fudge xoffset/yoffset as required
renderer->renderCreaturesImage(caretsprite, caretpose, xoffset, yoffset, has_alpha ? alpha : 0);
RenderOptions render_opts;
render_opts.alpha = parent->alpha;
renderer->renderCreaturesImage(caretsprite, caretpose, xoffset, yoffset, render_opts);
}

void TextEntryPart::tick() {
Expand Down
5 changes: 4 additions & 1 deletion src/TextPart.cpp
@@ -1,5 +1,6 @@
#include "TextPart.h"

#include "Agent.h"
#include "Backend.h"
#include "Engine.h"
#include "TextEntryPart.h"
Expand Down Expand Up @@ -262,7 +263,9 @@ void TextPart::partRender(RenderTarget* renderer, int xoffset, int yoffset, Text
if (((unsigned char)lines[i].text[x]) < 32)
continue; // TODO: replace with space or similar?
int spriteid = ((unsigned char)lines[i].text[x]) - 32;
renderer->renderCreaturesImage(sprite_to_use, spriteid, somex + currentx, yoff + currenty, has_alpha ? alpha : 0);
RenderOptions render_opts;
render_opts.alpha = parent->alpha;
renderer->renderCreaturesImage(sprite_to_use, spriteid, somex + currentx, yoff + currenty, render_opts);
if ((caretdata) && (caretdata->caretpos == lines[i].offset + x))
caretdata->renderCaret(renderer, somex + currentx, yoff + currenty);
currentx += textsprite->width(spriteid) + charspacing;
Expand Down
3 changes: 1 addition & 2 deletions src/backends/NullBackend.h
Expand Up @@ -26,8 +26,7 @@

class NullRenderTarget : public RenderTarget {
public:
virtual void renderCreaturesImage(creaturesImage&, unsigned int, int, int, uint8_t, bool) {}
virtual void renderCreaturesImage(const std::shared_ptr<creaturesImage>&, unsigned int, int, int, uint8_t, bool) {}
virtual void renderCreaturesImage(creaturesImage&, unsigned int, int, int, RenderOptions) {}
virtual void renderLine(int, int, int, int, unsigned int) {}
virtual void blitRenderTarget(RenderTarget*, int, int, int, int) {}
virtual unsigned int getWidth() const { return 800; }
Expand Down
15 changes: 5 additions & 10 deletions src/backends/SDLBackend.cpp
Expand Up @@ -309,7 +309,7 @@ unsigned int SDLRenderTarget::getHeight() const {
return drawableheight / scale - viewport_offset_top - viewport_offset_bottom;
}

void SDLRenderTarget::renderCreaturesImage(creaturesImage& img, unsigned int frame, int x, int y, uint8_t transparency, bool mirror) {
void SDLRenderTarget::renderCreaturesImage(creaturesImage& img, unsigned int frame, int x, int y, RenderOptions options) {
if ((x + img.width(frame) <= 0 || x >= (int)getWidth()) && (y + img.height(frame) <= 0 || y >= (int)getHeight())) {
return;
}
Expand All @@ -321,8 +321,8 @@ void SDLRenderTarget::renderCreaturesImage(creaturesImage& img, unsigned int fra
SDL_Texture* tex = img.getTextureForFrame(frame).as<SDL_Texture>();
assert(tex);

SDL_SetTextureAlphaMod(tex, 255 - transparency);
SDL_RendererFlip flip = mirror ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
SDL_SetTextureAlphaMod(tex, options.alpha);
SDL_RendererFlip flip = options.mirror ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;

SDL_Rect srcrect;
srcrect.x = img.getXOffsetForFrame(frame);
Expand All @@ -333,18 +333,13 @@ void SDLRenderTarget::renderCreaturesImage(creaturesImage& img, unsigned int fra
SDL_Rect destrect;
destrect.x = x;
destrect.y = y + viewport_offset_top;
destrect.w = srcrect.w;
destrect.h = srcrect.h;
destrect.w = (options.override_drawsize ? options.overridden_drawwidth : srcrect.w) * options.scale;
destrect.h = (options.override_drawsize ? options.overridden_drawheight : srcrect.h) * options.scale;

SDL_SetRenderTarget(parent->renderer, texture);
SDL_RenderCopyEx(parent->renderer, tex, &srcrect, &destrect, 0, nullptr, flip);
}

void SDLRenderTarget::renderCreaturesImage(const std::shared_ptr<creaturesImage>& img, unsigned int frame, int x, int y, uint8_t transparency, bool mirror) {
assert(img.get() != nullptr);
renderCreaturesImage(*img.get(), frame, x, y, transparency, mirror);
}

void SDLRenderTarget::renderClear() {
SDL_SetRenderDrawColor(parent->renderer, 0, 0, 0, 255);
SDL_SetRenderTarget(parent->renderer, texture);
Expand Down
3 changes: 1 addition & 2 deletions src/backends/SDLBackend.h
Expand Up @@ -40,8 +40,7 @@ class SDLRenderTarget : public RenderTarget {
SDLRenderTarget(SDLBackend* p) { parent = p; }

public:
void renderCreaturesImage(creaturesImage& tex, unsigned int frame, int x, int y, uint8_t transparency = 0, bool mirror = false);
void renderCreaturesImage(const std::shared_ptr<creaturesImage>& tex, unsigned int frame, int x, int y, uint8_t transparency = 0, bool mirror = false);
void renderCreaturesImage(creaturesImage& tex, unsigned int frame, int x, int y, RenderOptions options = {});
void renderLine(int x1, int y1, int x2, int y2, unsigned int colour);
void blitRenderTarget(RenderTarget* src, int x, int y, int w, int h);
unsigned int getWidth() const;
Expand Down
137 changes: 97 additions & 40 deletions src/caos/caosVM_agent.cpp
Expand Up @@ -1464,6 +1464,20 @@ void c_DCOR(caosVM* vm) {
vm->targ->displaycore = core_on;
}

/**
MIRA (command) mirror_on (integer)
%status maybe
Turns mirroring of the TARG agent's current sprite on or off (0 or 1).
*/
void c_MIRA(caosVM* vm) {
VM_PARAM_INTEGER(mirror_on)

valid_agent(vm->targ);
caos_assert(mirror_on == 0 || mirror_on == 1);
vm->targ->draw_mirrored = mirror_on;
}

/**
MIRA (integer)
%status maybe
Expand All @@ -1472,31 +1486,61 @@ void c_DCOR(caosVM* vm) {
*/
void v_MIRA(caosVM* vm) {
valid_agent(vm->targ);
vm->result.setInt(vm->targ->draw_mirrored);
}

// TODO: correct?
SpritePart* p = vm->getCurrentSpritePart();
caos_assert(p);
/**
FLIP (command) onoroff (integer)
%status stub
%variants sm
vm->result.setInt(p->draw_mirrored);
Tell the agent to draw the current sprite vertically flipped.
*/
void c_FLIP(caosVM* vm) {
VM_PARAM_INTEGER(onoroff);
valid_agent(vm->targ);
caos_assert(onoroff == 0 || onoroff == 1);
// TODO (this isn't actually used anywhere, afaict)
}

/**
MIRA (command) mirror_on (integer)
%status maybe
FLIP (integer)
%status stub
%variants sm
Turns mirroring of the TARG agent's current sprite on or off (0 or 1).
Is the current sprite for this agent vertically flipped?
*/
void c_MIRA(caosVM* vm) {
VM_PARAM_INTEGER(mirror_on)
void v_FLIP(caosVM* vm) {
valid_agent(vm->targ);
// TODO (this isn't actually used anywhere, afaict)
vm->result.setInt(0);
}

/**
ROTA (command) angle (integer)
%status stub
%variants sm
Tell the agent to draw the current sprite rotated clockwise by the given angle a value between 0 and 360.
*/
void c_ROTA(caosVM* vm) {
VM_PARAM_INTEGER(angle)

valid_agent(vm->targ);
caos_assert(angle >= 0 && angle <= 360);
// TODO: doesn't actually do anything in original engine?
}

// TODO: what does 'current sprite' mean?
// TODO: correct?
SpritePart* p = vm->getCurrentSpritePart();
caos_assert(p);
/**
ROTA (integer)
%status stub
%variants sm
p->draw_mirrored = mirror_on;
By what angle is the current sprite for this agent rotated returns angle between 0 and 360.
*/
void v_ROTA(caosVM* vm) {
valid_agent(vm->targ);
vm->result.setInt(0);
}

/**
Expand All @@ -1518,35 +1562,24 @@ void v_DISQ(caosVM* vm) {
}

/**
ALPH (command) alpha_value (integer) enable (integer)
ALPH (command) transparency (integer) enable (integer)
%status maybe
Sets the degree of alpha blending on the TARG agent, to a value from 0 (solid) to 256
(invisible). The second parameter will turn alpha blending on and off.
*/
void c_ALPH(caosVM* vm) {
VM_PARAM_INTEGER(enable)
VM_PARAM_INTEGER(alpha_value)
VM_PARAM_INTEGER(transparency)

if (alpha_value < 0)
alpha_value = 0;
else if (alpha_value > 255)
alpha_value = 255;
caos_assert(transparency >= 0 && transparency <= 256);
if (transparency == 256) {
transparency = 255;
}
caos_assert(enable == 0 || enable == 1);

valid_agent(vm->targ);

CompoundAgent* c = dynamic_cast<CompoundAgent*>(vm->targ.get());
if (c && vm->part == -1) {
for (auto& part : c->parts) {
part->has_alpha = enable;
part->alpha = alpha_value;
}
} else {
CompoundPart* p = vm->targ->part(vm->part);
caos_assert(p);
p->has_alpha = enable;
p->alpha = alpha_value;
}
vm->targ->alpha = enable ? 255 - transparency : 255;
}

/**
Expand Down Expand Up @@ -2042,32 +2075,54 @@ void v_XIST(caosVM* vm) {
}

/**
SCLE (command) pose (integer) scaleby (integer)
SCLE (command) scaleby (float) yesorno (integer)
%status done
%variants sm
*/
void c_SCLE_sm(caosVM* vm) {
VM_PARAM_INTEGER(yesorno)
VM_PARAM_FLOAT(scaleby)

valid_agent(vm->targ);

caos_assert(yesorno == 0 || yesorno == 1);
vm->targ->scle = yesorno ? scaleby : 1.0;
}

/**
SCLE (command) pose(integer) scaleby (float)
%status stub
%variants cv
*/
void c_SCLE(caosVM* vm) {
VM_PARAM_INTEGER(scaleby)
void c_SCLE_cv(caosVM* vm) {
VM_PARAM_FLOAT(scaleby)
VM_PARAM_INTEGER(pose)

valid_agent(vm->targ);

caos_assert(pose == 1 || pose == -1);

// TODO
}

/**
STRC (command) width (integer) height (integer) enable (integer)
%status stub
%variants sm
Draw the current agent (or part? don't know) with the given width/height (ie, stretch the sprite). Set enable to 1 to enable, or 0 to disable.
Draw the current agent with the given width/height (ie, stretch the sprite). Set enable to 1 to enable, or 0 to disable.
*/
void c_STRC(caosVM* vm) {
VM_PARAM_INTEGER(enable)
VM_PARAM_INTEGER(height)
VM_PARAM_INTEGER(width)

valid_agent(vm->targ);

// TODO
caos_assert(enable == 0 || enable == 1);
// TODO: does this affect agent's width/height?
vm->targ->strc = enable;
vm->targ->strc_width = width;
vm->targ->strc_height = height;
}

/**
Expand Down Expand Up @@ -2178,7 +2233,9 @@ void c_SHAD(caosVM* vm) {

valid_agent(vm->targ);

// TODO
// TODO: only used by clams in Sea-Monkeys.
// Intensity doesn't map directly to alpha 0.0–1.0, maybe 0–0.5?
// Needs to either only be on primary part, or all shadows rendered before all parts
}

/**
Expand Down

0 comments on commit b481012

Please sign in to comment.