Skip to content
This repository has been archived by the owner on Aug 23, 2023. It is now read-only.

Commit

Permalink
It clicks
Browse files Browse the repository at this point in the history
  • Loading branch information
corwinn committed Jan 31, 2023
1 parent 1941ea8 commit 703ba78
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 11 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
MAKEFLAGS += rR

APP = main
LOG ?= -DLOG_FILE
PLATFORM ?= posix
RENDER_API ?= gl
WIN_SYSTEM ?= $(RENDER_API)/sdl
Expand All @@ -43,7 +44,7 @@ CXX ?= clang++
H3R_TEST ?=
_W = -Wall -Wextra -Wshadow
_O = -O0 -g -DH3R_DEBUG -DH3R_MM -fno-exceptions -fno-threadsafe-statics \
$(H3R_TEST) -DGL_GLEXT_PROTOTYPES
$(H3R_TEST) -DGL_GLEXT_PROTOTYPES $(LOG)
_F = -fsanitize=address,undefined,integer,leak -fvisibility=hidden
#TODO release build _F = -fvisibility=hidden -fno-rtti
_L = -Wl,--as-needed -lpthread -lz -lSDL2 -lSDL2_mixer -lGL
Expand Down
15 changes: 14 additions & 1 deletion Makefile.mingw
Original file line number Diff line number Diff line change
Expand Up @@ -35,31 +35,44 @@
MAKEFLAGS += rR

APP = h3r.exe
APPS = h3r-static.exe
LOG ?= -DLOG_FILE
PLATFORM ?= windows
STATIC ?= TODO
RENDER_API ?= gl
WIN_SYSTEM ?= gl/sdl
CC = ccache x86_64-w64-mingw32-clang
CXX = ccache x86_64-w64-mingw32-clang++
CC_SYSROOT = $(P)
H3R_TEST ?=
_W = -Wall -Wextra -Wshadow
_O = -O0 -g -DH3R_DEBUG -DH3R_MM -fno-exceptions -fno-threadsafe-statics \
$(H3R_TEST) -DGL_GLEXT_PROTOTYPES -DSDL_MAIN_HANDLED -Umain -Dmain=WinMain
$(H3R_TEST) -DGL_GLEXT_PROTOTYPES -DSDL_MAIN_HANDLED -Umain -Dmain=WinMain \
$(LOG)
_F = -fvisibility=hidden
#TODO release build _F = -fvisibility=hidden -fno-rtti
_L = -mwindows -mconsole -lglu32 -lopengl32 -Wl,--as-needed -lzlib \
-lSDL2 -lSDL2_mixer
_Ls = -static -mwindows -mconsole -lglu32 -lopengl32 -Wl,--as-needed \
-lzlibstatic -lwinmm -limm32 -lole32 -loleaut32 -lversion -ldinput8 \
-lsetupapi -lSDL2 -lSDL2_mixer
_I = -I. -Ios -Ios/$(PLATFORM) -Iutils -Iui -Istream -Iasync -Igame \
-Igame/$(RENDER_API) \
-Ios/ui -Ios/ui/$(WIN_SYSTEM) `$(CC_SYSROOT)/bin/sdl2-config --cflags`

# c++14 is required for h3r_gl.h
CXXFLAGS = $(_I) -std=c++14 $(_O) $(_F) $(_W)
SRC = $(wildcard ./*/*.cpp)
SRC += $(wildcard os/$(PLATFORM)/*.cpp)
SRC += $(wildcard game/$(RENDER_API)/*.cpp)
SRC += $(wildcard os/ui/$(WIN_SYSTEM)/*.cpp)
SRC := $(filter-out ./prior_publish/%,$(SRC))
OBJ = $(patsubst %.cpp,%.o,$(SRC))

$(APP): main.a main.o h3r_game.o
$(CXX) $(_F) $^ -o $@ $(_L)
$(APPS): main.a main.o h3r_game.o
$(CXX) $(_F) $^ -o $@ $(_Ls)

%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $@
Expand Down
121 changes: 121 additions & 0 deletions stream/h3r_sdlrwops.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**** BEGIN LICENSE BLOCK ****
BSD 3-Clause License
Copyright (c) 2021-2023, the wind.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**** END LICENCE BLOCK ****/

#ifndef _H3R_SDLRWOPS_H_
#define _H3R_SDLRWOPS_H_

#include "h3r.h"
// #include "h3r_criticalsection.h"
#include "h3r_log.h"
#include "h3r_string.h"
#include <SDL2/SDL_mixer.h>

H3R_NAMESPACE

/*static inline void TheWayIsShut()
{
static OS::CriticalSection one_by_one_please {};
}*/

// Translate Stream to SDL_RWops:
// SDL_RWops * SDL_RWFromStream(Stream & s)
// The SDL_RWops shall be closed by Mix_LoadWAV_RW(), so no need to do
// funny things just yet.
// Supports the zipinflatestream.
//LATER cache; The people at SDL have really thought this through. I can only
// observe and learn how to design things.
//TODO be careful; this shall not work if the input stream does not support
// seek
class SdlRWopsStream final : public Stream
{
#define public public:
#define private private:
public struct RWops final
{
// Sint64 (*)(SDL_RWops *) size - Size()
// Sint64 (*)(SDL_RWops *, Sint64, int) seek
// size_t (*)(SDL_RWops *, void *, size_t, size_t) read
// size_t (*)(SDL_RWops *, const void *, size_t, size_t) write
// int (*)(SDL_RWops *) close
struct SDL_RWops SdlStream;
Stream & Data;
off_t DataSize;
RWops(Stream & data) : Data{data}, DataSize{data.Size ()}
{
SdlStream.type = SDL_RWOPS_UNKNOWN;
SdlStream.size = [](SDL_RWops * h) -> Sint64
{
return reinterpret_cast<RWops*>(h)->Data.Size ();
};
SdlStream.seek = [](SDL_RWops * h, Sint64 o, int whence) -> Sint64
{
Stream & s = reinterpret_cast<RWops*>(h)->Data;
switch (whence) {
case RW_SEEK_CUR: if (o < 0) o += s.Tell (); break;
case RW_SEEK_END: o = s.Size () - o; break;
default: break;
}
s.Reset (); s.Seek (o); return s.Tell ();
};
SdlStream.read =
[](SDL_RWops * h, void * buf, size_t s, size_t n) -> size_t
{
SdlRWopsStream::RWops * ops = reinterpret_cast<RWops*>(h);
if (ops->Data.Tell () == ops->DataSize)
return (-1); // wrong design; EOF is platform specific
ops->Data.Read (buf, s*n);
return n;
};
SdlStream.write = nullptr;
SdlStream.close = [](SDL_RWops *) -> int { return 0; };
}
~RWops()
{
}
};
private RWops _ops;
public SdlRWopsStream(Stream * s) : Stream {s}, _ops{*this} {}
public ~SdlRWopsStream() override {}
public inline operator SDL_RWops *()
{
return reinterpret_cast<SDL_RWops *>(&_ops);
}
};

#undef public
#undef private

NAMESPACE_H3R

#endif
70 changes: 64 additions & 6 deletions ui/h3r_button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "h3r_def.h"
#include "h3r_log.h"
#include "h3r_string.h"
#include "h3r_sdlrwops.h"

H3R_NAMESPACE

Expand All @@ -48,13 +49,13 @@ Button::Button(const String & res_name, Control * base)
auto btn_def_n = btn_def.Query (n);
if (! btn_def_n) {
H3R_NS::Log::Err (String::Format (
"Can't find %s[%s]", res_name.AsZStr (), n.AsZStr ()));
"Can't find %s[%s]" EOL, res_name.AsZStr (), n.AsZStr ()));
return;
}
auto byte_arr_ptr = btn_def_n->ToRGBA ();
if (! byte_arr_ptr || byte_arr_ptr->Empty ()) {
H3R_NS::Log::Err (String::Format (
"Can't load %s[%s]", res_name.AsZStr (), n.AsZStr ()));
"Can't load %s[%s]" EOL, res_name.AsZStr (), n.AsZStr ()));
return;
}

Expand All @@ -73,14 +74,25 @@ Button::Button(const String & res_name, Control * base)
btn_def_n->Height (),
byte_arr_ptr->operator byte * (), 4);

//TODO to function; or description;
n = res_name.ToLower ().Replace (".def", "s.pcx");
btn_def_n = btn_def.Query (n);
byte_arr_ptr = btn_def_n->ToRGBA ();
_es = TexCache::One ()->Cache (
btn_def_n->Width (),
btn_def_n->Height (),
byte_arr_ptr->operator byte * (), 4);

float fw = static_cast<float>(btn_def_n->Width ()),
fh = static_cast<float>(btn_def_n->Height ());
GLfloat v[32] {
GLfloat v[48] {
0,0,_en.l,_en.t, 0,fh,_en.l,_en.b, fw,0,_en.r,_en.t, fw,fh,_en.r,_en.b,
0,0,_eh.l,_eh.t, 0,fh,_eh.l,_eh.b, fw,0,_eh.r,_eh.t, fw,fh,_eh.r,_eh.b};
0,0,_eh.l,_eh.t, 0,fh,_eh.l,_eh.b, fw,0,_eh.r,_eh.t, fw,fh,_eh.r,_eh.b,
0,0,_es.l,_es.t, 0,fh,_es.l,_es.b, fw,0,_es.r,_es.t, fw,fh,_es.r,_es.b
};
glGenBuffers (1, &_vbo);
glBindBuffer (GL_ARRAY_BUFFER, _vbo);
glBufferData (GL_ARRAY_BUFFER, 32*sizeof(GLfloat), v, GL_STATIC_DRAW);
glBufferData (GL_ARRAY_BUFFER, 48*sizeof(GLfloat), v, GL_STATIC_DRAW);
}

void Button::OnMouseMove(const EventArgs & e)
Expand All @@ -96,6 +108,49 @@ void Button::OnMouseMove(const EventArgs & e)
ClientRectangle ().Size.X, ClientRectangle ().Size.Y));*/
}

static Mix_Chunk * global_fx1[MIX_CHANNELS] {};

void Button::OnMouseDown(const EventArgs &)
{
if (! _mouse_over) return;
_mouse_down = true;
Log::Info ("MouseDown" EOL);
auto stream = Game::GetResource ("BUTTON.wav");
if (! stream) {
Log::Err ("Can't load BUTTON.wav" EOL);
return;
}
SdlRWopsStream wav_ops {stream};
int freesrc = true;
Mix_Chunk * wav_chunk = Mix_LoadWAV_RW (wav_ops, freesrc);
if (! wav_chunk) {
Log::Err ("Mix_LoadWAV_RW: can't load BUTTON.wav" EOL);
return;
}
//TODO This complicates things a little bit
Mix_ChannelFinished ([](int c) {
if (global_fx1[c]) {
printf ("Mix_FreeChunk at global_fx1" EOL);
Mix_FreeChunk (global_fx1[c]);
global_fx1[c] = nullptr;
}
});
global_fx1[Mix_PlayChannel (-1, wav_chunk, 0)] = wav_chunk;
}

void Button::OnMouseUp(const EventArgs &)
{
//TODO Chain of Responsibility can really come in handy here. You clicked on
// one control - that's it: the others need not get notified. I don't
// need the bubbling/tunneling madness of the "WPF" here.
if (! _mouse_down) return; // It was not me
_mouse_down = false;
// If you release the button outside of the of the thing you clicked on
// there shall be no mouse click event.
if (! _mouse_over) return;
Log::Info ("MouseUp" EOL);
}

void Button::OnRender(GC &)
{
glLoadIdentity ();
Expand All @@ -106,7 +161,10 @@ void Button::OnRender(GC &)

GLint ofs = 0;
TexCache::Bind (_en); // It looks like a tex. bind, but it could be not
if (_mouse_over) { TexCache::Bind (_eh); ofs = 4; }
if (_mouse_over) {
if (_mouse_down) {TexCache::Bind (_es); ofs = 8;}
else { TexCache::Bind (_eh); ofs = 4; }
}
glBindBuffer (GL_ARRAY_BUFFER, _vbo);

glTranslatef (Pos ().X, Pos ().Y, 0);
Expand Down
8 changes: 6 additions & 2 deletions ui/h3r_button.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ H3R_NAMESPACE
// Its size is stored at the resource it is created from.
class Button: public Control
{
private: TexCache::Entry _en;
private: TexCache::Entry _eh;
private: TexCache::Entry _en; // up
private: TexCache::Entry _eh; // hover
private: TexCache::Entry _es; // down
private: GLuint _vbo {}; // one more to go

public: Button(const String &, Control * = nullptr);
Expand All @@ -60,8 +61,11 @@ class Button: public Control

public: virtual void OnRender(GC &) override;
public: virtual void OnMouseMove(const EventArgs &) override;
public: virtual void OnMouseDown(const EventArgs &) override;
public: virtual void OnMouseUp(const EventArgs &) override;

private: bool _mouse_over {};
private: bool _mouse_down {};
};

NAMESPACE_H3R
Expand Down
2 changes: 1 addition & 1 deletion ui/h3r_mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ MainWindow::MainWindow(OSWindow * actual_window)
Pcx main_window_background {Game::GetResource ("GamSelBk.pcx")};
auto byte_arr_ptr = main_window_background.ToRGB ();
if (! byte_arr_ptr || byte_arr_ptr->Empty ()) {
H3R_NS::Log::Err ("Failed to load GamSelBk.pcx");
H3R_NS::Log::Err ("Failed to load GamSelBk.pcx" EOL);
return;
}
_e1 = TexCache::One ()->Cache (
Expand Down

0 comments on commit 703ba78

Please sign in to comment.