Skip to content

Add KeyEvent class #261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ target_sources(scratchcpp
include/scratchcpp/stage.h
include/scratchcpp/sprite.h
include/scratchcpp/itimer.h
include/scratchcpp/keyevent.h
)

add_library(zip SHARED
Expand Down
37 changes: 37 additions & 0 deletions include/scratchcpp/keyevent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "global.h"
#include "spimpl.h"

namespace libscratchcpp
{

class KeyEventPrivate;

class LIBSCRATCHCPP_EXPORT KeyEvent
{
public:
enum class Type
{
Any,
Space,
Left,
Up,
Right,
Down,
Enter
};

KeyEvent(Type type = Type::Any);
KeyEvent(const std::string &name);

Type type() const;
const std::string &name() const;

private:
spimpl::impl_ptr<KeyEventPrivate> impl;
};

} // namespace libscratchcpp
3 changes: 3 additions & 0 deletions src/scratch/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,7 @@ target_sources(scratchcpp
entity.cpp
entity_p.cpp
entity_p.h
keyevent.cpp
keyevent_p.cpp
keyevent_p.h
)
34 changes: 34 additions & 0 deletions src/scratch/keyevent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: Apache-2.0

#include <scratchcpp/keyevent.h>

#include "keyevent_p.h"

namespace libscratchcpp
{

/*! Constructs KeyEvent. */
KeyEvent::KeyEvent(Type type) :
impl(spimpl::make_impl<KeyEventPrivate>(type))
{
}

/*! Constructs KeyEvent from a key name. */
KeyEvent::KeyEvent(const std::string &name) :
impl(spimpl::make_impl<KeyEventPrivate>(name))
{
}

/*! Returns the type of the key. */
KeyEvent::Type KeyEvent::type() const
{
return impl->type;
}

/*! Returns the name of the key. */
const std::string &KeyEvent::name() const
{
return impl->name;
}

} // namespace libscratchcpp
105 changes: 105 additions & 0 deletions src/scratch/keyevent_p.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// SPDX-License-Identifier: Apache-2.0

#include <unordered_map>
#include <algorithm>

#include "keyevent_p.h"

namespace libscratchcpp
{

static std::unordered_map<KeyEvent::Type, std::string> KEY_NAME = {
{ KeyEvent::Type::Space, "space" }, { KeyEvent::Type::Left, "left arrow" }, { KeyEvent::Type::Up, "up arrow" },
{ KeyEvent::Type::Right, "right arrow" }, { KeyEvent::Type::Down, "down arrow" }, { KeyEvent::Type::Enter, "enter" }
};

KeyEventPrivate::KeyEventPrivate(KeyEvent::Type type) :
type(type)
{
auto it = KEY_NAME.find(type);

if (it == KEY_NAME.cend())
this->type = KeyEvent::Type::Any;
else
name = it->second;
}

KeyEventPrivate::KeyEventPrivate(const std::string &name) :
name(name)
{
// See https://github.com/scratchfoundation/scratch-vm/blob/2a00145b8a968b04f278808858f79fa6d6e79946/src/io/keyboard.js#L93

// Convert from ASCII if a number was dropped in
try {
double numberDouble = std::stod(name);
long number = static_cast<long>(numberDouble);

if (numberDouble == number) {

if (number >= 48 && number <= 90) {
this->name = static_cast<char>(number);
convertNameToLowercase();

return;
}

switch (number) {
case 32:
type = KeyEvent::Type::Space;
break;

case 37:
type = KeyEvent::Type::Left;
break;

case 38:
type = KeyEvent::Type::Up;
break;

case 39:
type = KeyEvent::Type::Right;
break;

case 40:
type = KeyEvent::Type::Down;
break;

default:
break;
}

if (type != KeyEvent::Type::Any) {
this->name = KEY_NAME[type];
return;
}
}
} catch (...) {
}

// Check for a special key
for (const auto &[key, value] : KEY_NAME) {
if (value == name) {
type = key;
return;
}
}

// Use only the first character
if (this->name.size() > 1)
this->name = this->name[0];

// Check for the space character
if (this->name == " ") {
type = KeyEvent::Type::Space;
this->name = KEY_NAME[type];
}

convertNameToLowercase();
}

void KeyEventPrivate::convertNameToLowercase()
{
std::transform(this->name.begin(), this->name.end(), this->name.begin(), ::tolower);
}

} // namespace libscratchcpp
22 changes: 22 additions & 0 deletions src/scratch/keyevent_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <scratchcpp/keyevent.h>
#include <string>

namespace libscratchcpp
{

struct KeyEventPrivate
{
KeyEventPrivate(KeyEvent::Type type);
KeyEventPrivate(const std::string &name);

void convertNameToLowercase();

KeyEvent::Type type = KeyEvent::Type::Any;
std::string name;
};

} // namespace libscratchcpp
14 changes: 14 additions & 0 deletions test/scratch_classes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,17 @@ target_link_libraries(
)

gtest_discover_tests(variable_test)

# keyevent_test
add_executable(
keyevent_test
keyevent_test.cpp
)

target_link_libraries(
keyevent_test
GTest::gtest_main
scratchcpp
)

gtest_discover_tests(keyevent_test)
Loading