mirror of
https://github.com/overte-org/overte.git
synced 2025-04-12 10:42:10 +02:00
Merge pull request #10711 from burtsloane/midi
Midi support for Entities
This commit is contained in:
commit
d4e72df928
12 changed files with 466 additions and 6 deletions
|
@ -13,7 +13,7 @@ setup_memory_debugger()
|
||||||
link_hifi_libraries(
|
link_hifi_libraries(
|
||||||
audio avatars octree gpu model fbx entities
|
audio avatars octree gpu model fbx entities
|
||||||
networking animation recording shared script-engine embedded-webserver
|
networking animation recording shared script-engine embedded-webserver
|
||||||
physics plugins
|
controllers physics plugins midi
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
@ -195,7 +195,7 @@ link_hifi_libraries(
|
||||||
shared octree ktx gpu gl gpu-gl procedural model render
|
shared octree ktx gpu gl gpu-gl procedural model render
|
||||||
recording fbx networking model-networking entities avatars trackers
|
recording fbx networking model-networking entities avatars trackers
|
||||||
audio audio-client animation script-engine physics
|
audio audio-client animation script-engine physics
|
||||||
render-utils entities-renderer avatars-renderer ui auto-updater
|
render-utils entities-renderer avatars-renderer ui auto-updater midi
|
||||||
controllers plugins image trackers
|
controllers plugins image trackers
|
||||||
ui-plugins display-plugins input-plugins
|
ui-plugins display-plugins input-plugins
|
||||||
${NON_ANDROID_LIBRARIES}
|
${NON_ANDROID_LIBRARIES}
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#include <AssetClient.h>
|
#include <AssetClient.h>
|
||||||
#include <AssetUpload.h>
|
#include <AssetUpload.h>
|
||||||
#include <AutoUpdater.h>
|
#include <AutoUpdater.h>
|
||||||
|
#include <Midi.h>
|
||||||
#include <AudioInjectorManager.h>
|
#include <AudioInjectorManager.h>
|
||||||
#include <AvatarBookmarks.h>
|
#include <AvatarBookmarks.h>
|
||||||
#include <CursorManager.h>
|
#include <CursorManager.h>
|
||||||
|
@ -398,6 +399,10 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message->message == WM_DEVICECHANGE) {
|
||||||
|
Midi::USBchanged(); // re-scan the MIDI bus
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -567,6 +572,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
DependencyManager::set<SceneScriptingInterface>();
|
DependencyManager::set<SceneScriptingInterface>();
|
||||||
DependencyManager::set<OffscreenUi>();
|
DependencyManager::set<OffscreenUi>();
|
||||||
DependencyManager::set<AutoUpdater>();
|
DependencyManager::set<AutoUpdater>();
|
||||||
|
DependencyManager::set<Midi>();
|
||||||
DependencyManager::set<PathUtils>();
|
DependencyManager::set<PathUtils>();
|
||||||
DependencyManager::set<InterfaceDynamicFactory>();
|
DependencyManager::set<InterfaceDynamicFactory>();
|
||||||
DependencyManager::set<AudioInjectorManager>();
|
DependencyManager::set<AudioInjectorManager>();
|
||||||
|
|
3
libraries/midi/CMakeLists.txt
Normal file
3
libraries/midi/CMakeLists.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
set(TARGET_NAME midi)
|
||||||
|
setup_hifi_library(Network)
|
||||||
|
link_hifi_libraries(shared networking)
|
275
libraries/midi/src/Midi.cpp
Normal file
275
libraries/midi/src/Midi.cpp
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
//
|
||||||
|
// Midi.cpp
|
||||||
|
// libraries/midi/src
|
||||||
|
//
|
||||||
|
// Created by Burt Sloane
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Midi.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtCore/QLoggingCategory>
|
||||||
|
|
||||||
|
|
||||||
|
#if defined Q_OS_WIN32
|
||||||
|
#include "Windows.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined Q_OS_WIN32
|
||||||
|
const int MIDI_BYTE_MASK = 0x0FF;
|
||||||
|
const int MIDI_SHIFT_NOTE = 8;
|
||||||
|
const int MIDI_SHIFT_VELOCITY = 16;
|
||||||
|
#endif
|
||||||
|
const int MIDI_STATUS_MASK = 0x0F0;
|
||||||
|
const int MIDI_NOTE_OFF = 0x080;
|
||||||
|
const int MIDI_NOTE_ON = 0x090;
|
||||||
|
const int MIDI_CONTROL_CHANGE = 0x0b0;
|
||||||
|
const int MIDI_CHANNEL_MODE_ALL_NOTES_OFF = 0x07b;
|
||||||
|
|
||||||
|
|
||||||
|
static Midi* instance = NULL; // communicate this to non-class callbacks
|
||||||
|
static bool thruModeEnabled = false;
|
||||||
|
|
||||||
|
std::vector<QString> Midi::midiinexclude;
|
||||||
|
std::vector<QString> Midi::midioutexclude;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined Q_OS_WIN32
|
||||||
|
|
||||||
|
#pragma comment(lib, "Winmm.lib")
|
||||||
|
|
||||||
|
//
|
||||||
|
std::vector<HMIDIIN> midihin;
|
||||||
|
std::vector<HMIDIOUT> midihout;
|
||||||
|
|
||||||
|
|
||||||
|
void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
|
||||||
|
switch (wMsg) {
|
||||||
|
case MIM_OPEN:
|
||||||
|
// message not used
|
||||||
|
break;
|
||||||
|
case MIM_CLOSE:
|
||||||
|
for (int i = 0; i < midihin.size(); i++) {
|
||||||
|
if (midihin[i] == hMidiIn) {
|
||||||
|
midihin[i] = NULL;
|
||||||
|
instance->allNotesOff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MIM_DATA: {
|
||||||
|
int status = MIDI_BYTE_MASK & dwParam1;
|
||||||
|
int note = MIDI_BYTE_MASK & (dwParam1 >> MIDI_SHIFT_NOTE);
|
||||||
|
int vel = MIDI_BYTE_MASK & (dwParam1 >> MIDI_SHIFT_VELOCITY);
|
||||||
|
if (thruModeEnabled) {
|
||||||
|
instance->sendNote(status, note, vel); // relay the note on to all other midi devices
|
||||||
|
}
|
||||||
|
instance->noteReceived(status, note, vel); // notify the javascript
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CALLBACK MidiOutProc(HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
|
||||||
|
switch (wMsg) {
|
||||||
|
case MOM_OPEN:
|
||||||
|
// message not used
|
||||||
|
break;
|
||||||
|
case MOM_CLOSE:
|
||||||
|
for (int i = 0; i < midihout.size(); i++) {
|
||||||
|
if (midihout[i] == hmo) {
|
||||||
|
midihout[i] = NULL;
|
||||||
|
instance->allNotesOff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Midi::sendNote(int status, int note, int vel) {
|
||||||
|
for (int i = 0; i < midihout.size(); i++) {
|
||||||
|
if (midihout[i] != NULL) {
|
||||||
|
midiOutShortMsg(midihout[i], status + (note << MIDI_SHIFT_NOTE) + (vel << MIDI_SHIFT_VELOCITY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Midi::MidiSetup() {
|
||||||
|
midihin.clear();
|
||||||
|
midihout.clear();
|
||||||
|
|
||||||
|
MIDIINCAPS incaps;
|
||||||
|
for (unsigned int i = 0; i < midiInGetNumDevs(); i++) {
|
||||||
|
midiInGetDevCaps(i, &incaps, sizeof(MIDIINCAPS));
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (int j = 0; j < midiinexclude.size(); j++) {
|
||||||
|
if (midiinexclude[j].toStdString().compare(incaps.szPname) == 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) { // EXCLUDE AN INPUT BY NAME
|
||||||
|
HMIDIIN tmphin;
|
||||||
|
midiInOpen(&tmphin, i, (DWORD_PTR)MidiInProc, NULL, CALLBACK_FUNCTION);
|
||||||
|
midiInStart(tmphin);
|
||||||
|
midihin.push_back(tmphin);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDIOUTCAPS outcaps;
|
||||||
|
for (unsigned int i = 0; i < midiOutGetNumDevs(); i++) {
|
||||||
|
midiOutGetDevCaps(i, &outcaps, sizeof(MIDIINCAPS));
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (int j = 0; j < midioutexclude.size(); j++) {
|
||||||
|
if (midioutexclude[j].toStdString().compare(outcaps.szPname) == 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) { // EXCLUDE AN OUTPUT BY NAME
|
||||||
|
HMIDIOUT tmphout;
|
||||||
|
midiOutOpen(&tmphout, i, (DWORD_PTR)MidiOutProc, NULL, CALLBACK_FUNCTION);
|
||||||
|
midihout.push_back(tmphout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allNotesOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::MidiCleanup() {
|
||||||
|
allNotesOff();
|
||||||
|
|
||||||
|
for (int i = 0; i < midihin.size(); i++) {
|
||||||
|
if (midihin[i] != NULL) {
|
||||||
|
midiInStop(midihin[i]);
|
||||||
|
midiInClose(midihin[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < midihout.size(); i++) {
|
||||||
|
if (midihout[i] != NULL) {
|
||||||
|
midiOutClose(midihout[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
midihin.clear();
|
||||||
|
midihout.clear();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void Midi::sendNote(int status, int note, int vel) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::MidiSetup() {
|
||||||
|
allNotesOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::MidiCleanup() {
|
||||||
|
allNotesOff();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Midi::noteReceived(int status, int note, int velocity) {
|
||||||
|
if (((status & MIDI_STATUS_MASK) != MIDI_NOTE_OFF) &&
|
||||||
|
((status & MIDI_STATUS_MASK) != MIDI_NOTE_ON)) {
|
||||||
|
return; // NOTE: only sending note-on and note-off to Javascript
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap eventData;
|
||||||
|
eventData["status"] = status;
|
||||||
|
eventData["note"] = note;
|
||||||
|
eventData["velocity"] = velocity;
|
||||||
|
emit midiNote(eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
Midi::Midi() {
|
||||||
|
instance = this;
|
||||||
|
#if defined Q_OS_WIN32
|
||||||
|
midioutexclude.push_back("Microsoft GS Wavetable Synth"); // we don't want to hear this thing
|
||||||
|
#endif
|
||||||
|
MidiSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
Midi::~Midi() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::playMidiNote(int status, int note, int velocity) {
|
||||||
|
sendNote(status, note, velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::allNotesOff() {
|
||||||
|
sendNote(MIDI_CONTROL_CHANGE, MIDI_CHANNEL_MODE_ALL_NOTES_OFF, 0); // all notes off
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::resetDevices() {
|
||||||
|
MidiCleanup();
|
||||||
|
MidiSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::USBchanged() {
|
||||||
|
instance->MidiCleanup();
|
||||||
|
instance->MidiSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
QStringList Midi::listMidiDevices(bool output) {
|
||||||
|
QStringList rv;
|
||||||
|
#if defined Q_OS_WIN32
|
||||||
|
if (output) {
|
||||||
|
MIDIOUTCAPS outcaps;
|
||||||
|
for (unsigned int i = 0; i < midiOutGetNumDevs(); i++) {
|
||||||
|
midiOutGetDevCaps(i, &outcaps, sizeof(MIDIINCAPS));
|
||||||
|
rv.append(outcaps.szPname);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MIDIINCAPS incaps;
|
||||||
|
for (unsigned int i = 0; i < midiInGetNumDevs(); i++) {
|
||||||
|
midiInGetDevCaps(i, &incaps, sizeof(MIDIINCAPS));
|
||||||
|
rv.append(incaps.szPname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::unblockMidiDevice(QString name, bool output) {
|
||||||
|
if (output) {
|
||||||
|
for (unsigned long i = 0; i < midioutexclude.size(); i++) {
|
||||||
|
if (midioutexclude[i].toStdString().compare(name.toStdString()) == 0) {
|
||||||
|
midioutexclude.erase(midioutexclude.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (unsigned long i = 0; i < midiinexclude.size(); i++) {
|
||||||
|
if (midiinexclude[i].toStdString().compare(name.toStdString()) == 0) {
|
||||||
|
midiinexclude.erase(midiinexclude.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::blockMidiDevice(QString name, bool output) {
|
||||||
|
unblockMidiDevice(name, output); // make sure it's only in there once
|
||||||
|
if (output) {
|
||||||
|
midioutexclude.push_back(name);
|
||||||
|
} else {
|
||||||
|
midiinexclude.push_back(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::thruModeEnable(bool enable) {
|
||||||
|
thruModeEnabled = enable;
|
||||||
|
}
|
||||||
|
|
72
libraries/midi/src/Midi.h
Normal file
72
libraries/midi/src/Midi.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// Midi.h
|
||||||
|
// libraries/midi/src
|
||||||
|
//
|
||||||
|
// Created by Burt Sloane
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_Midi_h
|
||||||
|
#define hifi_Midi_h
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
#include <QAbstractNativeEventFilter>
|
||||||
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Midi : public QObject, public Dependency {
|
||||||
|
Q_OBJECT
|
||||||
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
|
public:
|
||||||
|
void noteReceived(int status, int note, int velocity); // relay a note to Javascript
|
||||||
|
void sendNote(int status, int note, int vel); // relay a note to MIDI outputs
|
||||||
|
static void USBchanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::vector<QString> midiinexclude;
|
||||||
|
static std::vector<QString> midioutexclude;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void MidiSetup();
|
||||||
|
void MidiCleanup();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void midiNote(QVariantMap eventData);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
/// play a note on all connected devices
|
||||||
|
/// @param {int} status: 0x80 is noteoff, 0x90 is noteon (if velocity=0, noteoff), etc
|
||||||
|
/// @param {int} note: midi note number
|
||||||
|
/// @param {int} velocity: note velocity (0 means noteoff)
|
||||||
|
Q_INVOKABLE void playMidiNote(int status, int note, int velocity);
|
||||||
|
|
||||||
|
/// turn off all notes on all connected devices
|
||||||
|
Q_INVOKABLE void allNotesOff();
|
||||||
|
|
||||||
|
/// clean up and re-discover attached devices
|
||||||
|
Q_INVOKABLE void resetDevices();
|
||||||
|
|
||||||
|
/// ask for a list of inputs/outputs
|
||||||
|
Q_INVOKABLE QStringList listMidiDevices(bool output);
|
||||||
|
|
||||||
|
/// block an input/output by name
|
||||||
|
Q_INVOKABLE void blockMidiDevice(QString name, bool output);
|
||||||
|
|
||||||
|
/// unblock an input/output by name
|
||||||
|
Q_INVOKABLE void unblockMidiDevice(QString name, bool output);
|
||||||
|
|
||||||
|
/// repeat all incoming notes to all outputs (default disabled)
|
||||||
|
Q_INVOKABLE void thruModeEnable(bool enable);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Midi();
|
||||||
|
virtual ~Midi();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_Midi_h
|
|
@ -16,6 +16,6 @@ if (NOT ANDROID)
|
||||||
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
link_hifi_libraries(shared networking octree gpu procedural model model-networking ktx recording avatars fbx entities controllers animation audio physics image)
|
link_hifi_libraries(shared networking octree gpu procedural model model-networking ktx recording avatars fbx entities controllers animation audio physics image midi)
|
||||||
# ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit
|
# ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit
|
||||||
include_hifi_library_headers(gl)
|
include_hifi_library_headers(gl)
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
|
|
||||||
#include <Profile.h>
|
#include <Profile.h>
|
||||||
|
|
||||||
|
#include "../../midi/src/Midi.h" // FIXME why won't a simpler include work?
|
||||||
#include "MIDIEvent.h"
|
#include "MIDIEvent.h"
|
||||||
|
|
||||||
const QString ScriptEngine::_SETTINGS_ENABLE_EXTENDED_EXCEPTIONS {
|
const QString ScriptEngine::_SETTINGS_ENABLE_EXTENDED_EXCEPTIONS {
|
||||||
|
@ -667,6 +668,8 @@ void ScriptEngine::init() {
|
||||||
|
|
||||||
registerGlobalObject("Audio", DependencyManager::get<AudioScriptingInterface>().data());
|
registerGlobalObject("Audio", DependencyManager::get<AudioScriptingInterface>().data());
|
||||||
|
|
||||||
|
registerGlobalObject("Midi", DependencyManager::get<Midi>().data());
|
||||||
|
|
||||||
registerGlobalObject("Entities", entityScriptingInterface.data());
|
registerGlobalObject("Entities", entityScriptingInterface.data());
|
||||||
registerGlobalObject("Quat", &_quatLibrary);
|
registerGlobalObject("Quat", &_quatLibrary);
|
||||||
registerGlobalObject("Vec3", &_vec3Library);
|
registerGlobalObject("Vec3", &_vec3Library);
|
||||||
|
|
|
@ -13,7 +13,7 @@ if (APPLE)
|
||||||
|
|
||||||
set(TARGET_NAME oculusLegacy)
|
set(TARGET_NAME oculusLegacy)
|
||||||
setup_hifi_plugin()
|
setup_hifi_plugin()
|
||||||
link_hifi_libraries(shared gl gpu gpu-gl plugins ui ui-plugins display-plugins input-plugins)
|
link_hifi_libraries(shared gl gpu gpu-gl plugins ui ui-plugins display-plugins input-plugins midi)
|
||||||
|
|
||||||
include_hifi_library_headers(octree)
|
include_hifi_library_headers(octree)
|
||||||
|
|
||||||
|
|
50
scripts/tutorials/createMidiSphere.js
Normal file
50
scripts/tutorials/createMidiSphere.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// Created by James B. Pollack @imgntn on April 18, 2016.
|
||||||
|
// Adapted by Burt
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
//var SCRIPT_URL = "file:///e:/hifi/scripts/tutorials/entity_scripts/midiSphere.js";
|
||||||
|
var SCRIPT_URL = "http://hifi-files.s3-website-us-west-2.amazonaws.com/midiSphere.js";
|
||||||
|
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(0.5, Quat.getForward(Camera.getOrientation())));
|
||||||
|
|
||||||
|
var BALL_GRAVITY = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var BALL_DIMENSIONS = {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
z: 0.4
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var BALL_COLOR = {
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var midiSphereProperties = {
|
||||||
|
name: 'MIDI Sphere',
|
||||||
|
shapeType: 'sphere',
|
||||||
|
type: 'Sphere',
|
||||||
|
script: SCRIPT_URL,
|
||||||
|
color: BALL_COLOR,
|
||||||
|
dimensions: BALL_DIMENSIONS,
|
||||||
|
gravity: BALL_GRAVITY,
|
||||||
|
dynamic: false,
|
||||||
|
position: center,
|
||||||
|
collisionless: false,
|
||||||
|
ignoreForCollisions: true
|
||||||
|
};
|
||||||
|
|
||||||
|
var midiSphere = Entities.addEntity(midiSphereProperties);
|
||||||
|
|
||||||
|
Script.stop();
|
52
scripts/tutorials/entity_scripts/midiSphere.js
Normal file
52
scripts/tutorials/entity_scripts/midiSphere.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// midiSphere.js
|
||||||
|
//
|
||||||
|
// Script Type: Entity
|
||||||
|
// Created by James B. Pollack @imgntn on 9/21/2015
|
||||||
|
// Adapted by Burt
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// This script listens to MIDI and makes the ball change color.
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var _this;
|
||||||
|
|
||||||
|
function MidiSphere() {
|
||||||
|
_this = this;
|
||||||
|
this.clicked = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MidiSphere.prototype = {
|
||||||
|
preload: function(entityID) {
|
||||||
|
this.entityID = entityID;
|
||||||
|
Midi.midiNote.connect(function(eventData) {
|
||||||
|
print("MidiSphere.noteReceived: "+JSON.stringify(eventData));
|
||||||
|
Entities.editEntity(entityID, { color: { red: 2*eventData.note, green: 2*eventData.note, blue: 2*eventData.note} });
|
||||||
|
});
|
||||||
|
print("MidiSphere.preload");
|
||||||
|
},
|
||||||
|
unload: function(entityID) {
|
||||||
|
print("MidiSphere.unload");
|
||||||
|
},
|
||||||
|
|
||||||
|
clickDownOnEntity: function(entityID, mouseEvent) {
|
||||||
|
print("MidiSphere.clickDownOnEntity");
|
||||||
|
if (this.clicked) {
|
||||||
|
Entities.editEntity(entityID, { color: { red: 0, green: 255, blue: 255} });
|
||||||
|
this.clicked = false;
|
||||||
|
Midi.playMidiNote(144, 64, 0);
|
||||||
|
} else {
|
||||||
|
Entities.editEntity(entityID, { color: { red: 255, green: 255, blue: 0} });
|
||||||
|
this.clicked = true;
|
||||||
|
Midi.playMidiNote(144, 64, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// entity scripts should return a newly constructed object of our type
|
||||||
|
return new MidiSphere();
|
||||||
|
});
|
|
@ -12,8 +12,7 @@ setup_hifi_project(Quick Gui OpenGL)
|
||||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
|
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
|
||||||
|
|
||||||
# link in the shared libraries
|
# link in the shared libraries
|
||||||
link_hifi_libraries(shared networking model fbx ktx image octree gl gpu gpu-gl render model-networking networking render-utils entities entities-renderer animation audio avatars script-engine physics procedural)
|
link_hifi_libraries(shared networking model fbx ktx image octree gl gpu gpu-gl render model-networking networking render-utils entities entities-renderer animation audio avatars script-engine physics procedural midi)
|
||||||
|
|
||||||
|
|
||||||
package_libraries_for_deployment()
|
package_libraries_for_deployment()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue